summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/tests
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
committerYaco <franco@reevo.org>2020-06-04 11:01:00 -0300
commitfc7369835258467bf97eb64f184b93691f9a9fd5 (patch)
treedaabd60089d2dd76d9f5fb416b005fbe159c799d /www/wiki/extensions/SemanticMediaWiki/tests
first commit
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/tests')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/README.md126
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/autoloader.php74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/bootstrap.php47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpUnitEnvironment.php158
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkJsonScriptRunnerTest.php212
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkReporter.php22
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Benchmarker.php155
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/CliOutputFormatter.php74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-001.xml342
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-002.xml214
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/JobQueueBenchmarkRunner.php125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/MaintenanceBenchmarkRunner.php114
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageContentCopyBenchmarkRunner.php164
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageEditCopyBenchmarkRunner.php170
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageImportBenchmarkRunner.php120
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/QueryBenchmarkRunner.php169
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/README.md56
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-001.json53
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-002.json186
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/phpunit.quick.xml.dist39
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/DatabaseTestCase.php234
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/ExecutionTimeTestListener.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/EncodingIntegrationTest.php109
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/content.json26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/foaf.txt13
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/content.json14
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/test.xml68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/ImporterIntegrationTest.php78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/InterwikiDBIntegrationTest.php158
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ApiTestCaseProcessor.php122
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/P106.txt24
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.0.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.1.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.2.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.3.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.4.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.5.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.6.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/file-upload.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-480.pngbin0 -> 97253 bytes
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-88.pngbin0 -> 4024 bytes
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/numeric-sorting.txt20
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.1.txt20
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.2.txt27
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.3.txt11
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0303.txt7
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.de.txt11
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.fr.txt13
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0444.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0459-keyword-formatter-schema.json15
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-error.txt2
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-other-license.json4
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502.txt49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.friends.txt109
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.persons.txt46
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.visits.txt27
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-1.txt3
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-2.txt3
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.10.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.11.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.7.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.8.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.9.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.0.json1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.1.json1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.2.json1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.3.json1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.0.csv5
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.1.csv4
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.2.csv5
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.3.csv4
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.4.csv4
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.5.csv5
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.6.csv4
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.7.csv4
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.0.txt12
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.1.txt13
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.0.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.1.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.2.txt1
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon-intro.txt11
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon.txt2
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/skos-import.txt33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php510
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserHtmlTestCaseProcessor.php148
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserTestCaseProcessor.php247
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseInterpreter.php297
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseProcessor.php272
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/README.md612
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/RdfTestCaseProcessor.php141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/SpecialPageTestCaseProcessor.php199
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0001.json301
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0002.json106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0003.json71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0001.json108
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0101.json125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0102.json81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0103.json124
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0104.json159
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0105.json125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0201.json178
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0202.json94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0203.json78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0204.json52
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0205.json93
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0206.json44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0207.json202
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0208.json180
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0209.json73
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0210.json76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0211.json230
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0301.json212
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0302.json108
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0303.json150
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0304.json198
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0305.json190
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0306.json234
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0307.json150
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0308.json93
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0401.json68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0402.json540
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0801.json247
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0802.json81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0803.json169
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0804.json83
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0805.json63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0101.json174
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0102.json258
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0106.json67
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0107.json145
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0108.json117
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0109.json54
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0110.json43
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0111.json35
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0112.json58
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0113.json126
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0114.json85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0115.json130
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0202.json84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0203.json104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0204.json54
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0205.json87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0206.json105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0207.json89
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0208.json236
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0209.json247
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0210.json90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0211.json97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0212.json102
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0301.json62
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0302.json106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0303.json70
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0401.json153
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0402.json239
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0403.json118
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0404.json78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0405.json212
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0406.json60
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0407.json61
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0408.json45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0409.json217
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0410.json458
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0411.json151
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0412.json76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0413.json882
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0414.json395
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0415.json65
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0416.json281
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0417.json88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0418.json85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0419.json285
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0420.json108
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0421.json55
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0422.json124
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0423.json173
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0424.json115
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0425.json71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0426.json104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0427.json146
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0428.json47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0429.json189
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0430.json133
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0431.json84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0432.json186
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0433.json87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0434.json215
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0435.json66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0436.json114
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0437.json42
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0438.json61
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0439.json122
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0440.json187
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0441.json47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0442.json50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0443.json198
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0444.json207
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0445.json63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0446.json257
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0447.json78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0448.json74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0449.json156
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0450.json94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0451.json105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0452.json71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0453.json41
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0454.json52
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0455.json244
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0456.json108
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0457.json70
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0458.json72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0459.json119
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0460.json218
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0461.json92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0501.json35
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0502.json194
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0503.json106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0504.json49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0701.json76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0702.json99
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0703.json64
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0704.json56
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0705.json98
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0706.json183
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0707.json45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0708.json61
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0709.json104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0710.json66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0711.json149
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0712.json64
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0901.json112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0902.json65
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0903.json70
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0904.json98
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0905.json103
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0906.json69
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0907.json81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0908.json48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0909.json265
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0910.json134
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0911.json64
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0912.json171
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0913.json221
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0914.json88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0915.json112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0916.json62
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1000.json127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1001.json97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1002.json44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1003.json72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1004.json59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1005.json53
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1006.json78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1007.json57
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0101.json127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0102.json263
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0103.json223
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0104.json274
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0105.json338
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0201.json130
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0202.json123
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0203.json71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0204.json109
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0301.json134
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0401.json163
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0402.json248
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0501.json130
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0502.json84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0503.json87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0601.json77
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0602.json48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0603.json230
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0604.json192
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0605.json141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0606.json249
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0607.json116
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0608.json123
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0609.json78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0610.json94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0611.json62
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0612.json100
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0613.json182
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0614.json109
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0615.json148
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0616.json128
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0617.json127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0618.json133
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0619.json80
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0620.json134
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0621.json105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0622.json71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0623.json85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0701.json186
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0702.json177
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0703.json77
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0704.json52
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0801.json47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0802.json160
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0803.json140
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0804.json34
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0901.json379
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0902.json65
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0903.json347
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0904.json142
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0905.json209
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0906.json163
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0907.json111
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0908.json219
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0909.json180
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0910.json113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0911.json54
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1002.json167
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1003.json165
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1004.json175
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1101.json189
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1102.json95
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1103.json100
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1104.json86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1105.json94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1106.json116
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1107.json84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1108.json106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1200.json210
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1201.json114
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1202.json186
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1203.json271
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1204.json204
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1205.json102
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1206.json142
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1300.json80
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0001.json205
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0002.json86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0003.json208
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0004.json92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0005.json47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0006.json127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0007.json125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0008.json86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0009.json85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0010.json104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0011.json112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0012.json100
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0013.json105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0014.json76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0015.json77
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0016.json105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0017.json104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0018.json46
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0019.json52
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0020.json45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0001.json68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0002.json586
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0003.json131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0004.json49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0005.json83
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0006.json50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0007.json44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0008.json161
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0009.json67
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0010.json56
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0011.json136
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0012.json66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0013.json48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0014.json240
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0015.json71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0016.json128
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0017.json79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0018.json93
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0019.json40
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0020.json121
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0021.json81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0022.json248
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0023.json44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0024.json49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0025.json106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0026.json47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0027.json179
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0028.json94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0029.json185
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0030.json50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0031.json95
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0032.json65
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0033.json59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/bootstrap.json53
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/readmeContentsBuilder.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/version2TestCaseConverter.php222
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/en.json24
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-fallback.json14
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-partial.json11
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/LanguageContentTest.php102
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/PartialLanguageFallbackTest.php73
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/Fixtures/test-import-19.7.xml270
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/PopulateHashFieldTest.php45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/RemoveDuplicateEntitiesTest.php45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/SetupStoreMaintenanceTest.php83
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/ApiBrowseBySubjectDBIntegrationTest.php150
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php135
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/InternalParseBeforeLinksIntegrationTest.php62
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserAfterTidyIntegrationTest.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserFirstCallInitIntegrationTest.php190
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/TitleMoveCompleteIntegrationTest.php206
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/CategoryInstanceAndCategoryHierarchyTest.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/CategoryInstanceAndCategoryHierarchyTest-Mw-1-19-7.xml175
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/GenericLoremIpsumTest-Mw-1-19-7.xml270
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/PageWithTemplateInclusionTest-Mw-1-19-7.xml112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RecordDataTypeTest-Mw-1-19-7.xml279
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RedirectPageTest-Mw-1-19-7.xml113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/TimeDataTypeTest-Mw-1-19-7.xml159
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/cicero-de-finibus.xml69
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/dwc-import-example.xml307
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/DumpRdfMaintenanceTest.php138
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildConceptCacheMaintenanceTest.php127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildDataMaintenanceTest.php175
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildFulltextSearchTableTest.php60
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildPropertyStatisticsMaintenanceTest.php77
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/UpdateEntityCollationTest.php74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/PageWithTemplateInclusionTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RecordDataTypeTest.php228
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RedirectPageTest.php215
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/TimeDataTypeTest.php281
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php179
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/UpdateJobRoundtripTest.php231
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateEmptyParserOutputDBIntegrationTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateSQLStoreDBIntegrationTest.php249
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateTest.php216
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MWNamespaceCanonicalNameMatchTest.php87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MediaWikiIntegrationForRegisteredHookTest.php176
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/PredefinedPropertyAnnotationDBIntegrationTest.php105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/RedirectTargetFinderIntegrationTest.php260
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/SearchInPageDBIntegrationTest.php107
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Parser/InTextAnnotationParserTemplateTransclusionTest.php143
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/PropertyLabelCanonicalMatchTest.php165
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/CategoryClassQueryDBIntegrationTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ComparatorFilterConditionQueryDBIntegrationTest.php335
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ConjunctionQueryDBIntegrationTest.php246
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DatePropertyValueQueryDBIntegrationTest.php173
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DisjunctionQueryDBIntegrationTest.php238
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/GeneralQueryDBIntegrationTest.php139
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/InversePropertyRelationshipDBIntegrationTest.php132
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NamespaceQueryDBIntegrationTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NullQueryResultTest.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ProfileAnnotators/ProfileAnnotatorWithQueryProcessorIntegrationTest.php137
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QueryResultPrinterIntegrationTest.php113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QuerySourceIntegrationTest.php192
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/RandomQueryResultOrderIntegrationTest.php84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SortableQueryDBIntegrationTest.php178
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SpecialCharactersQueryDBIntegrationTest.php164
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/QueryResultQueryProcessorIntegrationTest.php214
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/RdfFileResourceTest.php100
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/QueryResultLookupWithoutBaseStoreIntegrationTest.php219
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/RepositoryRedirectLookupActiveConnectionTest.php111
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/RefreshSQLStoreDBIntegrationTest.php107
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/SubSemanticDataDBIntegrationTest.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/TableBuilder/TableBuilderIntegrationTest.php318
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializationDBIntegrationTest.php52
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializerDeserializerRoundtripTest.php196
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSortKeyUpdateDBIntegrationTest.php107
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataStorageDBIntegrationTest.php327
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticMediaWikiProvidedHookInterfaceIntegrationTest.php471
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SpecialAskTest.php122
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nJsonFileIntegrityTest.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nMsgKeyIntegrityTest.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/InstallationConfigurationIntegrityTest.php104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/LanguagesAccessibilityAndIntegrityTest.php107
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/ResourcesAccessibilityTest.php63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/TempFileRoundTripTest.php49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseContentHandler.php192
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseFileHandler.php466
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseScriptRunner.php322
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/PHPUnitCompat.php31
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterRegistryTestCase.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterTestCase.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SemanticMediaWikiTestCase.php260
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SpecialPageTestCase.php146
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestConfig.php73
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestEnvironment.php248
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ApplicationFactoryTest.php328
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CacheFactoryTest.php170
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CachedPropertyValuesPrefetcherTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ChangePropListenerTest.php74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CompatibilityModeTest.php26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/CallbackConnectionProviderTest.php69
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionManagerTest.php96
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionProviderRefTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataItemFactoryTest.php164
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/ContainerSemanticDataTest.php85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/SubSemanticDataTest.php138
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataTypeRegistryTest.php454
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataUpdaterTest.php352
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValueFactoryTest.php341
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsListValueTest.php106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsPatternValueTest.php220
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/BooleanValueTest.php205
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ErrorMsgTextValueTest.php121
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalFormatterUriValueTest.php169
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalIdentifierValueTest.php170
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ImportValueTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/InfoLinksProviderTest.php251
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/KeywordValueTest.php163
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/LanguageCodeValueTest.php98
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/MonolingualTextValueTest.php259
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/IntlNumberFormatterTest.php348
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/UnitConverterTest.php271
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyChainValueTest.php155
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyValueTest.php65
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ReferenceValueTest.php184
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/StringValueTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TelephoneUriValueTest.php30
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TemperatureValueTest.php207
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/ComponentsTest.php46
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/IntlTimeFormatterTest.php272
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/JulianDayTest.php122
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/TimezoneTest.php170
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TypesValueTest.php132
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/UniquenessConstraintValueTest.php71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/CodeStringValueFormatterTest.php153
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/DispatchingDataValueFormatterTest.php127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/MonolingualTextValueFormatterTest.php158
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NoValueFormatterTest.php82
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NumberValueFormatterTest.php215
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/PropertyValueFormatterTest.php521
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/ReferenceValueFormatterTest.php224
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/StringValueFormatterTest.php225
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/TimeValueFormatterTest.php548
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsListValueParserTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsPatternValueParserTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/ImportValueParserTest.php223
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/MonolingualTextValueParserTest.php91
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/PropertyValueParserTest.php171
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/TimeValueParserTest.php88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/AllowsListConstraintValueValidatorTest.php411
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/CompoundConstraintValueValidatorTest.php61
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PatternConstraintValueValidatorTest.php152
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PropertySpecificationConstraintValueValidatorTest.php71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/UniquenessConstraintValueValidatorTest.php190
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DefinesTest.php37
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/DispatchingDescriptionDeserializerTest.php96
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/MonolingualTextValueDescriptionDeserializerTest.php159
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/NumberValueDescriptionDeserializerTest.php113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/RecordValueDescriptionDeserializerTest.php137
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/SomeValueDescriptionDeserializerTest.php201
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/TimeValueDescriptionDeserializerTest.php124
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializerRegistryTest.php119
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/ExpDataDeserializerTest.php163
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/SemanticDataDeserializerTest.php69
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/ElasticClientTaskHandlerTest.php138
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/IndicesInfoProviderTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/MappingsInfoProviderTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/NodesInfoProviderTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/SettingsInfoProviderTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ConfigTest.php84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ClientTest.php78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ConnectionProviderTest.php118
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ElasticFactoryTest.php244
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Exception/ClientBuilderNotFoundExceptionTest.php27
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/FileIndexerTest.php86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerRecoveryJobTest.php88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerTest.php208
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RebuilderTest.php264
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/ReplicationStatusTest.php104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RolloverTest.php141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Lookup/ProximityPropertyValueLookupTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/AggregationsTest.php115
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ConditionTest.php144
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php145
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/SomeValueInterpreterTest.php369
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php129
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ExcerptsTest.php52
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/FieldMapperTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EncoderTest.php116
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EnumTest.php38
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventHandlerTest.php90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventListenerRegistryTest.php229
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemDeserializationExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataTypeLookupExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotReadableExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotWritableExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/ParameterNotFoundExceptionTest.php43
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PredefinedPropertyLabelMismatchExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyLabelNotResolvedExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyNotFoundExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/RedirectTargetUnresolvableExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SemanticDataImportExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SettingNotFoundExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/StoreNotFoundExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SubSemanticDataExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ConceptMapperTest.php142
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/DataItemMatchFinderTest.php152
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpElementTest.php93
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpLiteralTest.php272
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpNsResourceTest.php259
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpResourceTest.php193
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ElementFactoryTest.php136
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/EscaperTest.php160
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ExpResourceMapperTest.php266
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/AuxiliaryPropertyValueResourceBuilderTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ConceptPropertyValueResourceBuilderTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/DispatchingResourceBuilderTest.php125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ExternalIdentifierPropertyValueResourceBuilderTest.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ImportFromPropertyValueResourceBuilderTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/KeywordPropertyValueResourceBuilderTest.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/MonolingualTextPropertyValueResourceBuilderTest.php87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PredefinedPropertyValueResourceBuilderTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PreferredPropertyLabelResourceBuilderTest.php86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyDescriptionValueResourceBuilderTest.php86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyValueResourceBuilderTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/RedirectPropertyValueResourceBuilderTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/SortPropertyValueResourceBuilderTest.php158
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/UniquenessConstraintPropertyValueResourceBuilderTest.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/XsdValueMapperTest.php162
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/CachedFactboxTest.php535
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxFactoryTest.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxMagicWordsTest.php196
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxTest.php559
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/GlobalFunctionsTest.php137
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HashBuilderTest.php146
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HierarchyLookupTest.php421
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/DispatchingContentCreatorTest.php133
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/TextContentCreatorTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/XmlContentCreatorTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentModellerTest.php62
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/InvalidJsonContent/invalid.json26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/MissingSections/error.json16
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/NoImportFormat/error.json6
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/content.json26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/foaf.txt13
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImportContentsTest.php126
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImporterTest.php142
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonContentIteratorTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonImportContentsFileDirReaderTest.php118
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/InMemoryPoolCacheTest.php87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/IteratorFactoryTest.php85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/AppendIteratorTest.php80
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ChunkedIteratorTest.php69
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/CsvFileIteratorTest.php127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/MappingIteratorTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ResultIteratorTest.php100
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/FallbackFinderTest.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/JsonContentsFileReaderTest.php173
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LangTest.php320
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LanguageContentsTest.php204
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/LocalizerTest.php372
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ConceptCacheRebuilderTest.php224
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DataRebuilderTest.php420
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DistinctEntityDataRebuilderTest.php290
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DuplicateEntitiesDisposerTest.php187
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ExceptionFileLoggerTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceFactoryTest.php106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceHelperTest.php105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceLoggerTest.php67
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/PropertyStatisticsRebuilderTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiQueryResultFormatterTest.php344
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiRequestParameterFormatterTest.php100
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskArgsTest.php269
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskTest.php104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleAugmentorTest.php154
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleLookupTest.php119
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/CachingLookupTest.php138
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListAugmentorTest.php194
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListLookupTest.php127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PSubjectLookupTest.php84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PValueLookupTest.php281
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/SubjectLookupTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseByPropertyTest.php113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseBySubjectTest.php238
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseTest.php230
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/InfoTest.php180
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/PropertyListByApiRequestTest.php146
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/QueryTest.php137
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/TaskTest.php252
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/CollatorTest.php190
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/ConnectionProviderTest.php143
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/DatabaseTest.php609
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/LoadBalancerConnectionProviderTest.php73
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/OptionsBuilderTest.php78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/QueryTest.php321
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/SequenceTest.php93
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/TransactionProfilerTest.php64
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/DeepRedirectTargetResolverTest.php142
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/CallableUpdateTest.php237
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/ChangeTitleUpdateTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/TransactionalCallableUpdateTest.php395
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/EditInfoProviderTest.php274
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Exception/ExtendedPermissionsErrorTest.php31
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleDeleteTest.php121
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleFromTitleTest.php77
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleProtectCompleteTest.php207
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticlePurgeTest.php218
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleViewHeaderTest.php148
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BaseTemplateToolboxTest.php237
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforeDisplayNoArticleTextTest.php71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforePageDisplayTest.php182
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/EditPageFormTest.php161
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionSchemaUpdatesTest.php44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionTypesTest.php39
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/FileUploadTest.php168
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/GetPreferencesTest.php84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookHandlerTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookListenerTest.php26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookRegistryTest.php1733
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/InternalParseBeforeLinksTest.php459
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/LinksUpdateConstructedTest.php238
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/NewRevisionFromEditCompleteTest.php214
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/OutputPageParserOutputTest.php360
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ParserAfterTidyTest.php412
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/PersonalUrlsTest.php72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/RejectParserCacheValueTest.php66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderGetConfigVarsTest.php49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderTestModulesTest.php57
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinAfterContentTest.php357
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinTemplateNavigationTest.php82
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialSearchResultsPrependTest.php116
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialStatsAddExtraTest.php164
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsAlwaysKnownTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsMovableTest.php95
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleMoveCompleteTest.php121
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/UserChangeTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobFactoryTest.php179
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobQueueTest.php244
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationClassUpdateJobTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php229
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationUpdateJobTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/EntityIdDisposerJobTest.php98
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableRebuildJobTest.php84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableUpdateJobTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/NullJobTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ParserCachePurgeJobTest.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/PropertyStatisticsRebuildJobTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/RefreshJobTest.php175
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateDispatcherJobTest.php421
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateJobTest.php325
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/LocalTimeTest.php115
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MagicWordsFinderTest.php160
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/ManualEntryLoggerTest.php112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MediaWikiNsContentReaderTest.php56
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MessageBuilderTest.php112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MwCollaboratorFactoryTest.php263
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageCreatorTest.php47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageInfoProviderTest.php368
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageUpdaterTest.php311
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/RedirectTargetFinderTest.php76
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlColumnListRendererTest.php261
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlFormRendererTest.php225
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTableRendererTest.php178
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTemplateRendererTest.php72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/WikitextTemplateRendererTest.php54
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/CustomFormTest.php67
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FieldTest.php99
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsBuilderTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFactoryTest.php75
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFinderTest.php66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/NamespaceFormTest.php64
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/OpenFormTest.php73
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/SortFormTest.php57
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/QueryBuilderTest.php224
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchProfileFormTest.php141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultSetTest.php222
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultTest.php130
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchTest.php635
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/CacheStatisticsListTaskHandlerTest.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/ConfigurationListTaskHandlerTest.php80
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DataRefreshJobTaskHandlerTest.php151
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DeprecationNoticeTaskHandlerTest.php139
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DisposeJobTaskHandlerTest.php152
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DuplicateLookupTaskHandlerTest.php73
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/EntityLookupTaskHandlerTest.php222
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/FulltextSearchTableRebuildJobTaskHandlerTest.php152
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OperationalStatisticsListTaskHandlerTest.php138
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OutputFormatterTest.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/PropertyStatsRebuildJobTaskHandlerTest.php152
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/SupportListTaskHandlerTest.php74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TableSchemaTaskHandlerTest.php109
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TaskHandlerFactoryTest.php148
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/DownloadLinksWidgetTest.php40
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ErrorWidgetTest.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/FormatListWidgetTest.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HelpWidgetTest.php26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HtmlFormTest.php72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/LinksWidgetTest.php133
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/NavigationLinksWidgetTest.php147
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParameterInputTest.php106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersProcessorTest.php242
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersWidgetTest.php86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/QueryInputWidgetTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/SortWidgetTest.php77
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/UrlArgsTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/FieldBuilderTest.php36
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/GroupFormatterTest.php119
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/HtmlBuilderTest.php195
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/ValueFormatterTest.php102
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PageProperty/PageBuilderTest.php116
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PropertyLabelSimilarity/ContentsBuilderTest.php95
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageBuilderTest.php178
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageRequestOptionsTest.php286
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/QueryResultLookupTest.php141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAdminTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAskTest.php75
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialBrowseTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialDeferredRequestDispatcherTest.php197
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPagePropertyTest.php113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialProcessingErrorListTest.php77
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPropertyLabelSimilarityTest.php54
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialSearchByPropertyTest.php124
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialURIResolverTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/StripMarkerDecoderTest.php108
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleFactoryTest.php66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleLookupTest.php258
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MessageTest.php211
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceExaminerTest.php99
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceManagerTest.php315
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceUriFinderTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/OptionsTest.php233
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ConceptPageTest.php36
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ListBuilderTest.php88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ValueListBuilderTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilderTest.php157
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PageFactoryTest.php91
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PropertyPageTest.php58
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterListDocBuilderTest.php158
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterProcessorFactoryTest.php63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParametersTest.php52
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/InTextAnnotationParserTest.php703
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksEncoderTest.php156
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksProcessorTest.php139
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/RecursiveTextProcessorTest.php345
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/SemanticLinksParserTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserDataTest.php488
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctionFactoryTest.php210
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/AskParserFunctionTest.php585
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ConceptParserFunctionTest.php247
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DeclareParserFunctionTest.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DocumentationParserFunctionTest.php58
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ExpensiveFuncExecutionWatcherTest.php149
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/InfoParserFunctionTest.php54
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/RecurringEventsParserFunctionTest.php429
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SectionTagTest.php118
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SetParserFunctionTest.php239
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ShowParserFunctionTest.php287
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php738
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserParameterProcessorTest.php409
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PermissionPthValidatorTest.php484
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PostProcHandlerTest.php395
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ProcessingErrorMsgHandlerTest.php218
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAliasFinderTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotatorFactoryTest.php146
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/CategoryPropertyAnnotatorTest.php387
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/ChainablePropertyAnnotatorTest.php117
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/DisplayTitlePropertyAnnotatorTest.php236
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/EditProtectedPropertyAnnotatorTest.php232
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/MandatoryTypePropertyAnnotatorTest.php234
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/NullPropertyAnnotatorTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/PredefinedPropertyAnnotatorTest.php366
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/RedirectPropertyAnnotatorTest.php116
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SchemaPropertyAnnotatorTest.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SortKeyPropertyAnnotatorTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/TranslationPropertyAnnotatorTest.php160
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyChangePropagationNotifierTest.php209
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyLabelFinderTest.php206
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRegistryTest.php572
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRestrictionExaminerTest.php148
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationLookupTest.php486
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqExaminerTest.php331
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqMsgBuilderTest.php236
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/EditProtectionUpdaterTest.php233
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/ProtectionValidatorTest.php246
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DebugFormatterTest.php149
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DeferredTest.php45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DescriptionFactoryTest.php371
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Exception/ResultFormatNotFoundExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ExcerptsTest.php72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ClassDescriptionTest.php280
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConceptDescriptionTest.php100
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConjunctionTest.php254
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/DisjunctionTest.php297
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/NamespaceDescriptionTest.php96
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/SomePropertyTest.php506
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ThingDescriptionTest.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ValueDescriptionTest.php223
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/DescriptionProcessorTest.php258
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/LegacyParserTest.php380
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TermParserTest.php219
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TokenizerTest.php99
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/DeserializerTest.php210
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/FormatterTest.php97
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/SerializerTest.php112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestFactoryTest.php88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestTest.php191
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/DefaultParamDefinitionTest.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/ParamListProcessorTest.php406
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/QueryCreatorTest.php93
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotatorFactoryTest.php229
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DescriptionProfileAnnotatorTest.php90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DurationProfileAnnotatorTest.php84
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/FormatProfileAnnotatorTest.php70
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/NullProfileAnnotatorTest.php67
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/ParametersProfileAnnotatorTest.php90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SchemaLinkProfileAnnotatorTest.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SourceProfileAnnotatorTest.php85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/StatusCodeProfileAnnotatorTest.php88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryComparatorTest.php191
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryLinkerTest.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QuerySourceFactoryTest.php141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryStringifierTest.php302
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTest.php196
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTokenTest.php219
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/RemoteRequestTest.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/CachedQueryResultPrefetcherTest.php349
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResolverJournalTest.php63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResultFieldMatchFinderTest.php373
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/StringResultTest.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CategoryResultPrinterTest.php44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CsvFileExportPrinterTest.php70
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/FeedExportPrinterTest.php72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinter/ParameterDictionaryTest.php66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinterTest.php66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/NullResultPrinterTest.php43
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TableResultPrinterTest.php44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TemplateFileExportPrinterTest.php70
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ScoreSetTest.php93
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/QueryFactoryTest.php127
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/RequestOptionsTest.php126
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Rule/RuleTest.php28
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/BadHttpEndpointResponseExceptionTest.php49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/HttpEndpointConnectionExceptionTest.php26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/HttpResponseErrorMapperTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FalseConditionTest.php39
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FilterConditionTest.php51
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/SingletonConditionTest.php54
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/TrueConditionTest.php39
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/WhereConditionTest.php51
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/ConditionBuilderTest.php923
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php40
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php240
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php198
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php369
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/DisjunctionInterpreterTest.php483
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php552
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php128
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php593
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/EngineOptionsTest.php96
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryEngineTest.php526
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryResultFactoryTest.php201
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/RepositoryResultTest.php129
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/XmlResponseParserTest.php170
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/ReplicationDataTruncatorTest.php75
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryClientTest.php51
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectionProviderTest.php223
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/ElementaryRepositoryConnectorTest.php190
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FourstoreRepositoryConnectorTest.php25
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FusekiRepositoryConnectorTest.php24
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/GenericRepositoryConnectorTest.php24
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/RepositoryConnectorsExceptionTest.php147
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/VirtuosoRepositoryConnectorTest.php25
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryRedirectLookupTest.php292
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreFactoryTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreTest.php358
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/TurtleTriplesBuilderTest.php106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeDiffTest.php163
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeOpTest.php412
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/FieldChangeOpTest.php66
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php226
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangePropagationEntityFinderTest.php185
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ConceptCacheTest.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityRebuildDispatcherTest.php239
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingEntityLookupTest.php387
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingSemanticDataLookupTest.php238
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIBlobHandlerTest.php246
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIUriHandlerTest.php215
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIWikiPageHandlerTest.php165
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DataItemHandlerDispatcherTest.php132
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdCacheManagerTest.php150
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdChangerTest.php202
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdEntityFinderTest.php232
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/NativeEntityLookupTest.php212
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertiesLookupTest.php138
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertySubjectsLookupTest.php156
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SemanticDataLookupTest.php356
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/StubSemanticDataTest.php162
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SubobjectListFinderTest.php140
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/TraversalPropertyLookupTest.php140
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/UniquenessLookupTest.php134
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityValueUniquenessConstraintCheckerTest.php165
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/PropertyStatisticsInvalidArgumentExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/TableMissingIdFieldExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/InstallerTest.php348
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/CachedListLookupTest.php168
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyLabelSimilarityLookupTest.php147
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyUsageListLookupTest.php216
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/ProximityPropertyValueLookupTest.php202
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/RedirectTargetLookupTest.php112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UndeclaredPropertyListLookupTest.php285
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UnusedPropertyListLookupTest.php217
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UsageStatisticsListLookupTest.php184
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyStatisticsStoreTest.php378
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionBuilderTest.php182
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionTest.php72
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceDisposerTest.php362
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceFinderTest.php209
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableInfoFetcherTest.php208
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowDifferTest.php167
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowMapperTest.php206
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableUpdaterTest.php167
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksTableUpdaterTest.php215
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksUpdateJournalTest.php204
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/EntityIdListRelevanceDetectionFilterTest.php253
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryDependencyLinksStoreTest.php1034
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryReferenceBacklinksTest.php134
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryResultDependencyListResolverTest.php602
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependencyLinksStoreFactoryTest.php96
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/ConceptQuerySegmentBuilderTest.php71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php40
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php132
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ComparatorMapperTest.php86
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php241
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/DisjunctionConjunctionInterpreterTest.php139
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php83
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php511
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php167
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/EngineOptionsTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/MySQLValueMatchConditionBuilderTest.php213
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SQLiteValueMatchConditionBuilderTest.php236
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableRebuilderTest.php218
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableTest.php137
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableUpdaterTest.php215
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextChangeUpdaterTest.php204
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextSanitizerTest.php136
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/ValueMatchConditionBuilderTest.php143
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/FulltextSearchTableFactoryTest.php141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/HierarchyTempTableBuilderTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/OrderConditionTest.php130
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QueryEngineTest.php119
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuildManagerTest.php74
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuilderTest.php293
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListProcessorTest.php65
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentTest.php82
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngineFactoryTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RedirectStoreTest.php265
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RequestOptionsProcTest.php343
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/SQLStoreFactoryTest.php438
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/Examiner/HashFieldTest.php106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/FieldTypeTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/MySQLTableBuilderTest.php396
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/PostgresTableBuilderTest.php385
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/SQLiteTableBuilderTest.php331
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableBuilderTest.php83
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableTest.php145
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TemporaryTableBuilderTest.php134
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableFieldUpdaterTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableIntegrityExaminerTest.php329
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableSchemaManagerTest.php115
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentFormatterTest.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentHandlerTest.php26
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentTest.php183
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/HtmlBuilderTest.php104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaConstructionFailedExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaTypeNotFoundExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaDefinitionTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaFactoryTest.php118
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaValidatorTest.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SerializerFactoryTest.php170
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/ExpDataSerializerTest.php174
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/QueryResultSerializerTest.php286
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/SemanticDataSerializerTest.php113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServiceFactoryTest.php189
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServicesContainerBuildTest.php171
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/Exception/ServiceNotFoundExceptionTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServiceFactoryTest.php133
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServicesContainerBuildTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/MediaWikiServicesContainerBuildTest.php87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ServicesContainerTest.php149
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/SharedServicesContainerTest.php44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SiteTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StoreTest.php38
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StringConditionTest.php51
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/TypesRegistryTest.php96
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/BufferedStatsdCollectorTest.php196
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharArmorTest.php104
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharExaminerTest.php75
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CircularReferenceGuardTest.php82
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CsvTest.php227
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ErrorCodeFormatterTest.php48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/FileTest.php47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HmacSerializerTest.php132
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlColumnsTest.php297
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlDivTableTest.php71
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlModalTest.php47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTableTest.php118
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTabsTest.php78
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlVTabsTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ImageTest.php38
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/JsonSchemaValidatorTest.php121
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LoggerTest.php62
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LruTest.php80
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/NormalizerTest.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/StatsFormatterTest.php98
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TempFileTest.php33
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TimerTest.php49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TokenizerTest.php44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ByPageSemanticDataFinder.php144
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/ConnectionProvider.php49
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/TestDatabaseTableBuilder.php297
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/BulkFileProvider.php89
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/ContentsReader.php43
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/DummyFileCreator.php101
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/JsonFileReader.php122
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/LocalFileUpload.php179
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/BerlinFactsheet.php273
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/FranceFactsheet.php117
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/ParisFactsheet.php254
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.json13
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.txt3
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesCleaner.php57
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFactory.php40
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFileProvider.php63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesProvider.php165
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/InvalidCustomRespositoryConnector.php12
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/AreaProperty.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/BookRecordProperty.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CapitalOfProperty.php43
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CityCategory.php45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CoordinatesProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CountryCategory.php59
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/DescriptionProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/EmailProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FixtureProperty.php50
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FoundedProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/LocatedInProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationDensityProperty.php48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/StatusProperty.php48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TelephoneNumberProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TemperatureProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TitleProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/UrlProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/YearProperty.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/FakeRawResultProvider.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/boolean-sparql-result.xml6
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/empty-sparql-result.xml9
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/integer-type-literal-sparql-result.xml11
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/invalid-sparql-result.xml8
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result-utf8.xml17
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result.xml17
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/nontype-literal-sparql-result.xml12
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/string-type-literal-sparql-result.xml11
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/uri-resource-sparql-result.xml11
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/GlobalsProvider.php90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/InSemanticDataFetcher.php61
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/CoreMockObjectRepository.php661
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/FakeQueryStore.php42
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/IteratorMockBuilder.php125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MediaWikiMockObjectRepository.php517
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectBuilder.php195
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectRepository.php23
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockSuperUser.php39
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockTitle.php63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwApiFactory.php87
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwHooksHandler.php145
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Page/PageEditor.php106
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageCreator.php161
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageDeleter.php67
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageReader.php105
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageRefresher.php92
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ParserFactory.php53
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/JobQueueRunner.php156
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/MaintenanceRunner.php125
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/RunnerFactory.php81
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/XmlImportRunner.php172
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SemanticDataFactory.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SpyLogger.php60
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/StringBuilder.php42
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/UtilityFactory.php248
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ExportDataValidator.php91
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/HtmlValidator.php141
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/IncomingSemanticDataValidator.php99
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/NumberValidator.php63
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QueryResultValidator.php202
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QuerySegmentValidator.php79
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/SemanticDataValidator.php436
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/StringValidator.php113
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/TitleValidator.php45
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ValidatorFactory.php98
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/ContentParserTest.php330
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/RecordValueTest.php266
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/UriValueTest.php397
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/WikiPageValueTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/HighlighterTest.php117
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/InfolinkTest.php243
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryPrinterFactoryTest.php199
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryProcessorTest.php158
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/RecurringEventsTest.php410
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/ChangeTitleTest.php329
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DataUpdateTest.php409
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DeleteSubjectTest.php259
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SemanticDataTest.php710
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SettingsTest.php184
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SetupTest.php344
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SubobjectTest.php436
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/CommonDataItemTest.php41
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIConceptTest.php82
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIPropertyTest.php227
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DITimeTest.php168
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIWikiPageTest.php112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BlobTest.php47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BoolTest.php47
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_GeoCoordTest.php68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_NumberTest.php44
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DataItemTest.php110
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExpDataTest.php143
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExportSemanticDataTest.php344
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/SMWExporterTest.php102
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/formatters/MessageFormatterTest.php282
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/PropertiesQueryPageTest.php188
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/QueryPageTest.php140
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/UnusedPropertiesQueryPageTest.php155
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/WantedPropertiesQueryPageTest.php112
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/AggregatablePrinterTest.php335
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/DsvResultPrinterTest.php43
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/EmbeddedResultPrinterTest.php42
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/JsonResultPrinterTest.php128
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RawResultPrinterTest.php48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RdfResultPrinterTest.php42
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/ResultPrintersTest.php88
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialConceptsTest.php94
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialsTest.php155
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/QueryResultTest.php131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreFactoryTest.php85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreTest.php198
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreSmwIdsTest.php546
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreTest.php170
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/api/ext.smw.api.test.js190
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.data.test.js333
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.number.test.js73
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.property.test.js60
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.text.test.js80
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.time.test.js131
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.unknown.test.js68
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.uri.test.js90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.wikiPage.test.js240
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataValue.quantity.test.js90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/ext.smw.test.js216
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/query/ext.smw.query.test.js213
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/util/ext.smw.util.tooltip.test.js102
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/README.md57
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/blazegraph-store.properties53
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/install-mediawiki.sh48
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/install-semantic-mediawiki.sh85
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/install-services.sh239
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/openrdf-sesame-memory-repository.txt8
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/run-tests.sh20
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/update-configuration-settings.sh90
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/upload-coverage-report.sh14
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/tests/travis/virtuoso-sparql-permission.sql6
1258 files changed, 180108 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/README.md b/www/wiki/extensions/SemanticMediaWiki/tests/README.md
new file mode 100644
index 00000000..8ffee500
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/README.md
@@ -0,0 +1,126 @@
+Tests are commonly divided into a manual (without using any tool or automated
+script) and an automated scripted test approach.
+
+# Manual testing
+
+If you want to run some manual tests (either as scripted or exploratory test procedure) then you just have to:
+
+1. Download a related branch using `composer require "mediawiki/semantic-media-wiki:dev-foo` (where `foo` refers to the branch name) or in case you want to test the current master, use `@dev` or `dev-master` as version together with the `minimum-stability: dev` flag so that the branch/master can be fetched without any stability limitations.
+2. Run `composer dump-autoload` to ensure that all registered classes are correctly initialized before starting any test procedure.
+
+# Automated testing (PHPUnit)
+
+For the automated approach, Semantic MediaWiki relies on [PHPUnit][phpunit] as scripted testing methodology. Scripted tests are used to verify that an expected behaviour occurs for codified requirements on the given conditions.
+
+- Unit test refers to a script that verifies results for a unit, module, or class against an expected outcome in an isolated environment
+- Integration test (or functional test) normally combines multiple components into a single process and verifies the results in a semi-production like environment (including DB access, sample data etc.)
+- System test (and its individual modules) is treated as "black-box" to observe behaviour as a whole rather than its units
+
+## Running tests
+
+1. Verify that PHUnit is installed and in case it is not, use `composer require phpunit/phpunit:~4.8 --update-with-dependencies` to add the package
+2. Verify that your MediaWiki installation comes with its test files and folders (e.g. `/myMediawikiFolder/tests` ) in order for Semantic MediaWiki to have access to registered MW-core classes. If the `tests` folder is missing then you may follow the [release source](https://github.com/wikimedia/mediawiki/releases) to download the missing files.
+3. Run `composer phpunit` from the Semantic MediaWiki base directory (e.g. `/extensions/SemanticMediaWiki`) using a standard command line tool which should output something like:
+
+<pre>
+$ composer phpunit
+
+Semantic MediaWiki: 2.5.0-alpha (SMWSQLStore3, sqlite)
+MediaWiki: 1.28.0-alpha (Extension vendor autoloader)
+Site language: en
+
+Execution time: 2015-01-01 01:00
+Xdebug: Disabled (or not installed)
+
+PHPUnit 4.8.27 by Sebastian Bergmann and contributors.
+
+Runtime: PHP 5.6.8
+Configuration: /home/travis/build/SemanticMediaWiki/mw/extensions/SemanticMediaWiki/phpunit.xml.dist
+
+............................................................. 61 / 4069 ( 1%)
+............................................................. 122 / 4069 ( 2%)
+</pre>
+
+Information about PHPUnit in connection with MediaWiki can be found at [smw.org][smw] and [mediawiki.org][mw-phpunit-testing].
+
+## Writing tests
+
+Writing meaningful tests isn't difficult but requires some diligence on how to setup a test and its environment. One simple rule is to avoid the use of hidden expectations or inheritance as remedy for the "less code is good code" aesthetics. Allow the code to be readable and if possible follow the [arrange, act, assert][aaa] pattern.
+
+For a short introduction on "How to write a test for Semantic MediaWiki", have a look at [this](https://www.youtube.com/watch?v=v6JRfk5ZmsI) video.
+
+### Test cases
+
+The use of `MediaWikiTestCase` is discouraged (as its binds tests and the test
+environment to MediaWiki) and it is best to rely on `PHPUnit_Framework_TestCase`
+and where a MW database connection is required, use the `MwDBaseUnitTestCase`
+instead.
+
+* `QueryPrinterTestCase` base class for all query and result printers
+* `SpecialPageTestCase` derives from `SemanticMediaWikiTestCase`
+
+## Integration tests
+
+Integration tests are vital to confirm the behaviour of a component from an
+integrative perspective that occurs through an interplay with its surroundings.
+
+Those tests don't replace unit tests, they complement them to verify that
+an expected outcome does actually occur in combination with MediaWiki and
+other services.
+
+Integration tests can help reduce the recurrence of regressions or bugs, given
+that a developers follows a simple process:
+
+- Make a conjecture or hypothesis about the cause of the bug or regression
+- Find a minimal test case (using wiki text at this point should make it much
+easier to replicate a deviated behaviour)
+- Write a `JSON` test and have it __fail__
+- Apply a fix
+- Run the test again and then run all other integration tests to ensure nothing
+else was altered by accidentally introducing another regression not directly
+related to the one that has been fixed
+
+`SMW\Tests\Integration\` hosts most of the tests that target the validation of
+reciprocity with MediaWiki and/or other services such as:
+
+- Triple-stores (necessary for the `SPARQLStore`)
+- Extensions (`SESP`, `SBL` etc.)
+
+Some details about the integration test environment can be found [here](https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/master/tests/travis/README.md).
+
+### JSONScript integration tests
+
+One best practice approach in Semantic MediaWiki is to write integration tests as
+pseudo `JSONScript` to allow non-developers to review and understand the setup and
+requirements of its test scenarios.
+
+The `JSON` format was introduced as abstraction layer to lower the barrier of
+understanding of what is being tested by using the wikitext markup to help design
+test cases quicker without the need to learn how `PHPUnit` or internal `MediaWiki`
+objects work.
+
+A detailed description of the `JSONScript` together with a list of available test
+files can be found [here](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/README.md).
+
+## Benchmark tests
+
+For details, please have a look at the [benchmark guide](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Benchmark/README.md) document.
+
+# JavaScript (QUnit)
+
+Running qunit tests in connection with MediaWiki requires to execute
+[Special:JavaScriptTest][mw-qunit-testing]. QUnit tests are currently not
+executed on Travis (see [#136][issue-136]).
+
+# Miscellaneous
+* [Writing testable code](https://semantic-mediawiki.org/wiki/Help:Writing_testable_code)
+* [Code coverage in a nutshell](https://semantic-mediawiki.org/wiki/Help:Code_coverage_in_a_nutshell)
+* [Test Doubles](http://www.martinfowler.com/bliki/TestDouble.html) (mocks, stubs etc.) and [how to write them](http://phpunit.de/manual/4.1/en/test-doubles.html)
+
+[phpunit]: http://phpunit.de/manual/4.1/en/index.html
+[smw]: https://www.semantic-mediawiki.org/wiki/PHPUnit_tests
+[mw-phpunit-testing]: https://www.mediawiki.org/wiki/Manual:PHP_unit_testing
+[mw-qunit-testing]: https://www.mediawiki.org/wiki/Manual:JavaScript_unit_testing
+[issue-136]: https://github.com/SemanticMediaWiki/SemanticMediaWiki/pull/136
+[phpunit-fixtures]: http://phpunit.de/manual/current/en/fixtures.html
+[aaa]: http://c2.com/cgi/wiki?ArrangeActAssert
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/autoloader.php b/www/wiki/extensions/SemanticMediaWiki/tests/autoloader.php
new file mode 100644
index 00000000..4c605390
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/autoloader.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * Convenience autoloader to pre-register test classes
+ *
+ * Third-party users that require SMW as integration platform should
+ * add the following to the bootstrap.php
+ *
+ * require __DIR__ . '/../../SemanticMediaWiki/tests/autoloader.php'
+ */
+if ( PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' ) {
+ die( 'Not an entry point' );
+}
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die( 'MediaWiki is not available.' );
+}
+
+if ( !class_exists( 'SemanticMediaWiki' ) || SemanticMediaWiki::getVersion() === null ) {
+ die( "\nSemantic MediaWiki is not available, please check your LocalSettings or Composer settings.\n" );
+}
+
+if ( is_readable( $path = __DIR__ . '/../vendor/autoload.php' ) ) {
+ $autoloadType = "Extension vendor autoloader";
+} elseif ( is_readable( $path = __DIR__ . '/../../../vendor/autoload.php' ) ) {
+ $autoloadType = "MediaWiki vendor autoloader";
+} else {
+ die( 'To run the test suite it is required that packages are installed using Composer.' );
+}
+
+require __DIR__ . '/phpUnitEnvironment.php';
+$phpUnitEnvironment = new PHPUnitEnvironment();
+
+if ( $phpUnitEnvironment->hasDebugRequest( $GLOBALS['argv'] ) === false ) {
+ $phpUnitEnvironment->emptyDebugVars();
+}
+
+$phpUnitEnvironment->writeNewLn( "Semantic MediaWiki:", $phpUnitEnvironment->getVersion( 'smw' ) );
+$phpUnitEnvironment->writeLn( "MediaWiki:", $phpUnitEnvironment->getVersion( 'mw', [ 'type' => $autoloadType ] ) );
+$phpUnitEnvironment->writeLn( "Site language:", $phpUnitEnvironment->getSiteLanguageCode() );
+$phpUnitEnvironment->writeNewLn( "Execution time:", $phpUnitEnvironment->executionTime() );
+$phpUnitEnvironment->writeLn( "Debug logs:", ( $phpUnitEnvironment->enabledDebugLogs() ? 'Enabled' : 'Disabled' ) );
+$phpUnitEnvironment->writeLn( "Xdebug:", ( ( $version = $phpUnitEnvironment->getXdebugInfo() ) ? $version : 'Disabled (or not installed)' ) );
+$phpUnitEnvironment->writeNewLn();
+
+unset( $phpUnitEnvironment );
+
+/**
+ * Available to aid third-party extensions therefore any change should be made with
+ * care
+ *
+ * @since 2.0
+ */
+$autoloader = require $path;
+
+$autoloader->addPsr4( 'SMW\\Tests\\Utils\\', __DIR__ . '/phpunit/Utils' );
+
+$autoloader->addClassMap( [
+ 'SMW\Tests\TestEnvironment' => __DIR__ . '/phpunit/TestEnvironment.php',
+ 'SMW\Tests\TestConfig' => __DIR__ . '/phpunit/TestConfig.php',
+ 'SMW\Tests\PHPUnitCompat' => __DIR__ . '/phpunit/PHPUnitCompat.php',
+ 'SMW\Tests\DatabaseTestCase' => __DIR__ . '/phpunit/DatabaseTestCase.php',
+ 'SMW\Tests\JsonTestCaseScriptRunner' => __DIR__ . '/phpunit/JsonTestCaseScriptRunner.php',
+ 'SMW\Tests\JsonTestCaseFileHandler' => __DIR__ . '/phpunit/JsonTestCaseFileHandler.php',
+ 'SMW\Tests\JsonTestCaseContentHandler' => __DIR__ . '/phpunit/JsonTestCaseContentHandler.php',
+ 'SMW\Test\QueryPrinterTestCase' => __DIR__ . '/phpunit/QueryPrinterTestCase.php',
+ 'SMW\Test\QueryPrinterRegistryTestCase' => __DIR__ . '/phpunit/QueryPrinterRegistryTestCase.php',
+ 'SMW\Tests\SPARQLStore\RepositoryConnectors\ElementaryRepositoryConnectorTest' => __DIR__ . '/phpunit/Unit/SPARQLStore/RepositoryConnectors/ElementaryRepositoryConnectorTest.php',
+] );
+
+// 3.0
+class_alias( '\SMW\Tests\DatabaseTestCase', '\SMW\Tests\MwDBaseUnitTestCase' );
+
+return $autoloader;
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/bootstrap.php b/www/wiki/extensions/SemanticMediaWiki/tests/bootstrap.php
new file mode 100644
index 00000000..57c890f9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/bootstrap.php
@@ -0,0 +1,47 @@
+<?php
+
+use SMW\MediaWiki\Connection\Sequence;
+use SMW\ApplicationFactory;
+use SMW\SQLStore\SQLStore;
+
+if ( PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' ) {
+ die( 'Not an entry point' );
+}
+
+error_reporting( -1 );
+ini_set( 'display_errors', '1' );
+
+$autoloader = require __DIR__ . '/autoloader.php';
+
+$autoloader->addPsr4( 'SMW\\Test\\', __DIR__ . '/phpunit' );
+$autoloader->addPsr4( 'SMW\\Tests\\', __DIR__ . '/phpunit' );
+
+$autoloader->addClassMap( [
+ 'SMW\Tests\DataItemTest' => __DIR__ . '/phpunit/includes/dataitems/DataItemTest.php',
+ 'SMW\Maintenance\RebuildConceptCache' => __DIR__ . '/../maintenance/rebuildConceptCache.php',
+ 'SMW\Maintenance\RebuildData' => __DIR__ . '/../maintenance/rebuildData.php',
+ 'SMW\Maintenance\RebuildPropertyStatistics' => __DIR__ . '/../maintenance/rebuildPropertyStatistics.php',
+ 'SMW\Maintenance\RebuildFulltextSearchTable' => __DIR__ . '/../maintenance/rebuildFulltextSearchTable.php',
+ 'SMW\Maintenance\DumpRdf' => __DIR__ . '/../maintenance/dumpRDF.php',
+ 'SMW\Maintenance\SetupStore' => __DIR__ . '/../maintenance/setupStore.php',
+ 'SMW\Maintenance\UpdateEntityCollation' => __DIR__ . '/../maintenance/updateEntityCollation.php',
+ 'SMW\Maintenance\RemoveDuplicateEntities' => __DIR__ . '/../maintenance/removeDuplicateEntities.php'
+] );
+
+/**
+ * Register a shutdown function the invoke a final clean-up
+ */
+register_shutdown_function( function() {
+
+ if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
+ return;
+ }
+
+ // Reset any sequence modified during the test
+ $sequence = new Sequence(
+ ApplicationFactory::getInstance()->getConnectionManager()->getConnection( 'mw.db' )
+ );
+
+ $sequence->tablePrefix( '' );
+ $sequence->restart( SQLStore::ID_TABLE, 'smw_id' );
+} );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpUnitEnvironment.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpUnitEnvironment.php
new file mode 100644
index 00000000..0a05c762
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpUnitEnvironment.php
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * @private
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PHPUnitEnvironment {
+
+ /**
+ * @var array
+ */
+ private $gitHead = [];
+
+ /**
+ * @param array $args
+ *
+ * @return boolean
+ */
+ public function hasDebugRequest( $args ) {
+ return array_search( '--debug', $args ) || array_search( '--debug-tests', $args );
+ }
+
+ public function emptyDebugVars() {
+ $GLOBALS['wgDebugLogGroups'] = [];
+ $GLOBALS['wgDebugLogFile'] = '';
+ }
+
+ /**
+ * @return boolean
+ */
+ public function enabledDebugLogs() {
+ return $GLOBALS['wgDebugLogGroups'] !== [] || $GLOBALS['wgDebugLogFile'] !== '';
+ }
+
+ /**
+ * @return boolean|integer
+ */
+ public function getXdebugInfo() {
+
+ if ( extension_loaded( 'xdebug' ) && xdebug_is_enabled() ) {
+ return phpversion( 'xdebug' );
+ }
+
+ return false;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSiteLanguageCode() {
+ return $GLOBALS['wgLanguageCode'];
+ }
+
+ /**
+ * @return string
+ */
+ public function executionTime() {
+ $dateTimeUtc = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) );
+ return $dateTimeUtc->format( 'Y-m-d h:i' );
+ }
+
+ /**
+ * @param string $id
+ *
+ * @return array
+ */
+ public function getVersion( $id, $extra = [] ) {
+
+ $info = [];
+
+ if ( $id === 'smw' ) {
+ $store = str_replace(
+ [ '{', '}', '"', '(SMW', ':(', '))', ',' ],
+ [ '(', ')', '', 'SMW', ' (', ')', ', ' ],
+ json_encode( smwfGetStore()->getInfo(), JSON_UNESCAPED_SLASHES )
+ );
+
+ $info = [
+ SemanticMediaWiki::getVersion(),
+ 'git: ' . $this->getGitInfo( 'smw' ),
+ $store
+ ] + $extra;
+ }
+
+ if ( $id === 'mw' ) {
+ $info = [
+ $GLOBALS['wgVersion'],
+ 'git: ' . $this->getGitInfo( 'mw' )
+ ] + $extra;
+ }
+
+ return implode( ', ', $info );
+ }
+
+ /**
+ * @param string $id
+ *
+ * @return string
+ */
+ public function getGitInfo( $id ) {
+
+ if ( $this->gitHead === [] && class_exists( 'GitInfo' ) ) {
+ $this->gitHead = [
+ 'mw' => '',
+ 'smw' => ''
+ ];
+
+ $this->gitHead['mw'] = GitInfo::headSHA1();
+
+ if ( $this->gitHead['mw'] ) {
+ $this->gitHead['mw'] = substr( $this->gitHead['mw'], 0, 7 );
+ } else {
+ $this->gitHead['mw'] = 'N/A';
+ }
+
+ $gitInfo = new GitInfo( __DIR__ . '/..' );
+ $this->gitHead['smw'] = $gitInfo->getHeadSHA1();
+
+ if ( $this->gitHead['smw'] ) {
+ $this->gitHead['smw'] = substr( $this->gitHead['smw'], 0, 7 );
+ }
+ }
+
+ if ( isset( $this->gitHead[$id] ) ) {
+ return $this->gitHead[$id];
+ }
+ }
+
+ /**
+ * @param string $arg1
+ * @param string|array $arg2
+ *
+ * @return string
+ */
+ public function writeLn( $arg1, $arg2 ) {
+ return print sprintf( "%-20s%s\n", $arg1, $arg2 );
+ }
+
+ /**
+ * @param string $arg1
+ * @param string|array $arg2
+ *
+ * @return string
+ */
+ public function writeNewLn( $arg1 = '', $arg2 = '' ) {
+
+ if ( $arg1 === '' && $arg2 === '' ) {
+ return print "\n";
+ }
+
+ return print sprintf( "\n%-20s%s\n", $arg1, $arg2 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkJsonScriptRunnerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkJsonScriptRunnerTest.php
new file mode 100644
index 00000000..b95e6617
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkJsonScriptRunnerTest.php
@@ -0,0 +1,212 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+use SMW\ApplicationFactory;
+use SMW\Tests\JsonTestCaseFileHandler;
+use SMW\Tests\JsonTestCaseScriptRunner;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class BenchmarkJsonScriptRunnerTest extends JsonTestCaseScriptRunner {
+
+ /**
+ * @var PageImportBenchmarkRunner
+ */
+ private $pageImportBenchmarkRunner;
+
+ /**
+ * @var PageContentCopyBenchmarkRunner
+ */
+ private $pageContentCopyBenchmarkRunner;
+
+ /**
+ * @var PageEditCopyBenchmarkRunner
+ */
+ private $pageEditCopyBenchmarkRunner;
+
+ /**
+ * @var JobQueueBenchmarkRunner
+ */
+ private $jobQueueBenchmarkRunner;
+
+ /**
+ * @var MaintenanceBenchmarkRunner
+ */
+ private $maintenanceBenchmarkRunner;
+
+ /**
+ * @var QueryBenchmarkRunner
+ */
+ private $queryBenchmarkRunner;
+
+ /**
+ * @var array
+ */
+ private $benchmarkReports = [];
+
+ /**
+ * @see JsonTestCaseScriptRunner::$deletePagesOnTearDown
+ */
+ protected $deletePagesOnTearDown = true;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+ $benchmarker = new Benchmarker();
+
+ $this->pageImportBenchmarkRunner = new PageImportBenchmarkRunner(
+ $utilityFactory->newRunnerFactory()->newXmlImportRunner(),
+ $benchmarker
+ );
+
+ $this->pageContentCopyBenchmarkRunner = new PageContentCopyBenchmarkRunner(
+ $this->pageImportBenchmarkRunner,
+ $benchmarker,
+ $utilityFactory->newPageCreator(),
+ $utilityFactory->newPageReader()
+ );
+
+ // Variable set via phpunit.xml
+ $this->pageContentCopyBenchmarkRunner->setCopyCount(
+ isset( $GLOBALS['benchmarkPageCopyCount'] ) ? $GLOBALS['benchmarkPageCopyCount'] : null
+ );
+
+ $this->pageEditCopyBenchmarkRunner = new PageEditCopyBenchmarkRunner(
+ $this->pageImportBenchmarkRunner,
+ $benchmarker,
+ $utilityFactory->newPageCreator(),
+ $utilityFactory->newPageReader()
+ );
+
+ // Variable set via phpunit.xml
+ $this->pageEditCopyBenchmarkRunner->setEditRepetitionCount(
+ isset( $GLOBALS['benchmarkPageEditRepetitionCount'] ) ? $GLOBALS['benchmarkPageEditRepetitionCount'] : null
+ );
+
+ $this->jobQueueBenchmarkRunner = new JobQueueBenchmarkRunner(
+ ApplicationFactory::getInstance()->newJobFactory(),
+ $utilityFactory->newRunnerFactory()->newJobQueueRunner(),
+ $benchmarker
+ );
+
+ $this->maintenanceBenchmarkRunner = new MaintenanceBenchmarkRunner(
+ $utilityFactory->newRunnerFactory(),
+ $benchmarker
+ );
+
+ $this->queryBenchmarkRunner = new QueryBenchmarkRunner(
+ $this->getStore(),
+ ApplicationFactory::getInstance()->getQueryFactory()->newQueryParser(),
+ $benchmarker
+ );
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getTestCaseLocation
+ */
+ protected function getTestCaseLocation() {
+ return __DIR__ . '/TestCases';
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getTestCaseLocation
+ */
+ protected function getRequiredJsonTestCaseMinVersion() {
+ return '1';
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getAllowedTestCaseFiles
+ */
+ protected function getAllowedTestCaseFiles() {
+ return [];
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::runTestCaseFile
+ *
+ * @param JsonTestCaseFileHandler $jsonTestCaseFileHandler
+ */
+ protected function runTestCaseFile( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ $this->pageImportBenchmarkRunner->setTestCaseLocation(
+ $this->getTestCaseLocation()
+ );
+
+ $this->doRunImportBenchmarks( $jsonTestCaseFileHandler );
+ $this->doRunContentCopyBenchmarks( $jsonTestCaseFileHandler );
+ $this->doRunEditCopyBenchmarks( $jsonTestCaseFileHandler );
+ $this->doRunJobQueueBenchmarks( $jsonTestCaseFileHandler );
+ $this->doRunMaintenanceBenchmarks( $jsonTestCaseFileHandler );
+ $this->doRunQueryBenchmarks( $jsonTestCaseFileHandler );
+
+ $this->assertNotEmpty(
+ $this->benchmarkReports
+ );
+
+ $report = [
+ 'mediawiki' => $GLOBALS['wgVersion'],
+ 'semantic-mediawiki' => \SemanticMediaWiki::getVersion(),
+ 'environment' => $this->getStore()->getInfo(),
+ 'benchmarks' => $this->benchmarkReports
+ ];
+
+ $cliOutputFormatter = new CliOutputFormatter(
+ CliOutputFormatter::FORMAT_JSON
+ );
+
+ return print "\n\n" . $cliOutputFormatter->format( $report );
+ }
+
+ private function doRunImportBenchmarks( $jsonTestCaseFileHandler ) {
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'import' ) as $case ) {
+ $this->pageImportBenchmarkRunner->run( $case );
+ $this->benchmarkReports[md5(json_encode( $case ) )] = $this->pageImportBenchmarkRunner->getBenchmarkReport();
+ }
+ }
+
+ private function doRunContentCopyBenchmarks( $jsonTestCaseFileHandler ) {
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'contentCopy' ) as $case ) {
+ $this->pageContentCopyBenchmarkRunner->run( $case );
+ $this->benchmarkReports[md5(json_encode( $case ) )] = $this->pageContentCopyBenchmarkRunner->getBenchmarkReport();
+ }
+ }
+
+ private function doRunEditCopyBenchmarks( $jsonTestCaseFileHandler ) {
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'editCopy' ) as $case ) {
+ $this->pageEditCopyBenchmarkRunner->run( $case );
+ $this->benchmarkReports[md5(json_encode( $case ) )] = $this->pageEditCopyBenchmarkRunner->getBenchmarkReport();
+ }
+ }
+
+ private function doRunJobQueueBenchmarks( $jsonTestCaseFileHandler ) {
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'job' ) as $case ) {
+ $this->jobQueueBenchmarkRunner->run( $case );
+ $this->benchmarkReports[md5(json_encode( $case ) )] = $this->jobQueueBenchmarkRunner->getBenchmarkReport();
+ }
+ }
+
+ private function doRunMaintenanceBenchmarks( $jsonTestCaseFileHandler ) {
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'maintenance' ) as $case ) {
+ $this->maintenanceBenchmarkRunner->run( $case );
+ $this->benchmarkReports[md5(json_encode( $case ) )] = $this->maintenanceBenchmarkRunner->getBenchmarkReport();
+ }
+ }
+
+ private function doRunQueryBenchmarks( $jsonTestCaseFileHandler ) {
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'query' ) as $case ) {
+ $this->queryBenchmarkRunner->run( $case );
+ $this->benchmarkReports[md5(json_encode( $case ) )] = $this->queryBenchmarkRunner->getBenchmarkReport();
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkReporter.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkReporter.php
new file mode 100644
index 00000000..2881ce78
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/BenchmarkReporter.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+interface BenchmarkReporter {
+
+ /**
+ * @since 2.5
+ *
+ * @param array
+ */
+ public function getBenchmarkReport();
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Benchmarker.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Benchmarker.php
new file mode 100644
index 00000000..41f4c9a0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Benchmarker.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class Benchmarker {
+
+ /**
+ * @var array
+ */
+ private $container = [];
+
+ /**
+ * @var boolean
+ */
+ private $useAsSample = false;
+
+ /**
+ * @var integer
+ */
+ private $roundFactor;
+
+ /**
+ * @since 2.1
+ */
+ public function __construct( $roundFactor = 7 ) {
+ $this->roundFactor = $roundFactor;
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function clear() {
+ $this->container = [];
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param boalean $state false when takling about the entire population;
+ * true when it is a sample (a selection from a population)
+ */
+ public function useAsSample( $state = true ) {
+ $this->useAsSample = $state;
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param integer $roundFactor
+ */
+ public function roundBy( $roundFactor ) {
+ $this->roundFactor = $roundFactor;
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param integer $point
+ * @param integer $decimals
+ */
+ public function addBenchmarkPoint( $point, $decimals = 10 ) {
+ $this->container[] = number_format( $point, $decimals );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param integer[] $poins
+ */
+ public function addBenchmarkPoints( array $poins ) {
+ $this->container = $poins;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return integer
+ */
+ public function getSum() {
+ return $this->round( array_sum( $this->container ) );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return integer
+ */
+ public function getMean() {
+ return $this->round( $this->getSum() / count( $this->container ) );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return integer
+ */
+ public function getVariance() {
+
+ $mean = $this->getMean();
+ $count = count( $this->container );
+
+ $sumOfSquares = 0;
+
+ foreach ( $this->container as $value ) {
+ $sumOfSquares += pow( $value - $mean, 2 );
+ }
+
+ return $sumOfSquares / ( $this->useAsSample ? $count - 1 : $count );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return integer
+ */
+ public function getStandardDeviation() {
+ return $this->round( (float)sqrt( $this->getVariance() ) );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param integer $basis
+ *
+ * @return integer
+ */
+ public function getStandardScoreBy( $basis = 0 ) {
+ return $this->round( ( $basis - $this->getMean() ) / $this->getStandardDeviation() );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param integer $basis
+ *
+ * @return integer
+ */
+ public function getNormalizedValueBy( $basis = 1 ) {
+ return $this->round( $this->getMean() / $basis );
+ }
+
+ private function round( $value ) {
+ return round( $value, $this->roundFactor );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/CliOutputFormatter.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/CliOutputFormatter.php
new file mode 100644
index 00000000..9afd5484
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/CliOutputFormatter.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class CliOutputFormatter {
+
+ const FORMAT_TREE = 'format.tree';
+ const FORMAT_JSON = 'format.json';
+
+ /**
+ * @var string
+ */
+ private $formatType;
+
+ /**
+ * @since 2.5
+ *
+ * @param string $formatType
+ */
+ public function __construct( $formatType = self::FORMAT_TREE ) {
+ $this->formatType = $formatType;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $report
+ */
+ public function format( array $report ) {
+
+ if ( $this->formatType === self::FORMAT_TREE ) {
+ return $this->doFormatAsTree( $report );
+ }
+
+ return json_encode( $report, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT );
+ }
+
+ private function doFormatAsTree( $report, $label = '', $level = 1 ) {
+ $output = '';
+
+ if ( is_string( $label ) && $label !== '' ) {
+ $output .= sprintf( "%s- %s\n", str_repeat( ' ', $level ), $label );
+ $level++;
+ }
+
+ foreach ( $report as $key => $value ) {
+
+ $isDeeper = false;
+
+ if ( is_array( $value ) ) {
+ foreach ( $value as $p => $v ) {
+ if ( is_array( $v ) ) {
+ $isDeeper = true;
+ }
+ }
+ }
+
+ if ( $isDeeper ) {
+ $output .= $this->doFormatAsTree( $value, $key, $level + 1 );
+ } else {
+ $output .= sprintf( "%s- %s: %s\n", str_repeat( ' ', $level ), $key, json_encode( $value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) );
+ }
+ }
+
+ return $output;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-001.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-001.xml
new file mode 100644
index 00000000..7335eee6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-001.xml
@@ -0,0 +1,342 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Property:Has annotation uri</title>
+ <ns>102</ns>
+ <id>503</id>
+ <sha1>ifvt9xhpsfkv04ehcnhpw3i88s0fsb8</sha1>
+ <revision>
+ <id>1342</id>
+ <timestamp>2014-03-29T16:51:25Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="53">[[Has type::Annotation URI]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has boolean</title>
+ <ns>102</ns>
+ <id>502</id>
+ <sha1>l3b3eelfib1em61uurletnc4kb1xlzh</sha1>
+ <revision>
+ <id>1338</id>
+ <timestamp>2014-03-29T16:47:13Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Boolean]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="46">[[Has type::Boolean]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has date</title>
+ <ns>102</ns>
+ <id>14</id>
+ <sha1>473nf5knraq99k8zsrg6z7o3812tu61</sha1>
+ <revision>
+ <id>1330</id>
+ <timestamp>2014-03-29T16:38:59Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Date]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has email</title>
+ <ns>102</ns>
+ <id>500</id>
+ <sha1>9puenjhr9dntyg9obgtwhvaenn98rav</sha1>
+ <revision>
+ <id>1334</id>
+ <timestamp>2014-03-29T16:42:38Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Email]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="44">[[Has type::Email]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has number</title>
+ <ns>102</ns>
+ <id>494</id>
+ <sha1>9fqf0pft61g8qqb8qtz1i5ayr1rmu30</sha1>
+ <revision>
+ <id>1321</id>
+ <timestamp>2014-03-29T16:30:26Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Number]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="45">[[Has type::Number]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has page</title>
+ <ns>102</ns>
+ <id>489</id>
+ <sha1>4sq0eljhm3yty9cifkvel3mv646ag0y</sha1>
+ <revision>
+ <id>1319</id>
+ <timestamp>2014-03-29T16:29:46Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Page]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has quantity</title>
+ <ns>102</ns>
+ <id>495</id>
+ <sha1>1ulyevjgdofvfrp7b6b17n7p0p6oy4w</sha1>
+ <revision>
+ <id>1323</id>
+ <timestamp>2014-03-29T16:34:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="219">[[Has type::Quantity]] [[Category:Lorem ipsum]]
+
+* [[Corresponds to::1 km²]]
+* [[Corresponds to::0.38610 sq mi]]
+* [[Corresponds to::1000 m²]]
+* [[Corresponds to::247.1054 acre]]
+* [[Corresponds to::988.4215 rood]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has wattage</title>
+ <ns>102</ns>
+ <id>503</id>
+ <sha1>1ulyevjgdofvfrp7b6b17n7p0p6oy4w</sha1>
+ <revision>
+ <id>1355</id>
+ <timestamp>2014-03-29T16:34:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="219">[[Has type::Quantity]] [[Display units::kW]] [[Category:Lorem ipsum]]
+
+* [[Corresponds to::1 W, Watt, Watts]]
+* [[Corresponds to::0.001 kW]]
+* [[Corresponds to::0.0013410220 hp, bhp, horsepower]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has status</title>
+ <ns>102</ns>
+ <id>504</id>
+ <sha1>1ulyevjgdofvfrp7b6b17n7p0p6oy4w</sha1>
+ <revision>
+ <id>1365</id>
+ <timestamp>2014-03-29T16:34:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="219">[[Has type::Text]] [[Category:Lorem ipsum]]
+
+* [[Allows value::open]]
+* [[Allows value::closed]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has telephone number</title>
+ <ns>102</ns>
+ <id>505</id>
+ <sha1>1ulyevjgdofvfrp7b6b17n7p0p6oy4w</sha1>
+ <revision>
+ <id>1375</id>
+ <timestamp>2014-03-29T16:34:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="219">[[Has type::Telephone number]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has record</title>
+ <ns>102</ns>
+ <id>506</id>
+ <sha1>1ulyevjgdofvfrp7b6b17n7p0p6oy4w</sha1>
+ <revision>
+ <id>1385</id>
+ <timestamp>2014-03-29T16:34:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="219">[[Has type::Record]] [[Has fields::Has text; Has status]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has temperature</title>
+ <ns>102</ns>
+ <id>501</id>
+ <sha1>925639l5wc4pwdmufjgza10rstpb2oa</sha1>
+ <revision>
+ <id>1336</id>
+ <timestamp>2014-03-29T16:45:35Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Temperature]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="50">[[Has type::Temperature]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has text</title>
+ <ns>102</ns>
+ <id>491</id>
+ <sha1>qi7oxp4101tdesdm3vavpgpfn1qe68u</sha1>
+ <revision>
+ <id>1320</id>
+ <timestamp>2014-03-29T16:30:07Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Text]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has Url</title>
+ <ns>102</ns>
+ <id>499</id>
+ <sha1>1fw7q2wts7v11q1z6d31g89zorhco0i</sha1>
+ <revision>
+ <id>1332</id>
+ <timestamp>2014-03-29T16:40:28Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::URL]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="42">[[Has type::URL]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Lorem ipsum</title>
+ <ns>0</ns>
+ <id>493</id>
+ <sha1>94lztkh4kgb0mvjr87iyjfq4iv7ltlh</sha1>
+ <revision>
+ <id>1358</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="979">[[Has text::Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis neque leo scelerisque nec habitasse a lacus mattis. Accumsan tincidunt Sed adipiscing nec facilisis tortor Nunc Sed ipsum tellus.]] [[Has page::Turpis pellentesque]] id sociis pede ipsum Quisque. Eu sed sed porta Integer pulvinar accumsan leo in semper lobortis. Urna vel mattis [[Has page::Pellentesque ante]] iaculis tincidunt et consequat Aliquam dictum.
+
+* Has page: [[Has page::{{PAGENAME}}]]
+* Has number: [[Has number::1001]]
+* Has quantity: [[Has quantity::10.25 km²]]
+* Has date: [[Has date::1 Jan 2014]]
+* Has Url: [[Has Url::http://loremipsum.org/]]
+* Has annotation uri: [[Has annotation uri::http://loremipsum.org/foaf.rdf]]
+* Has email: [[Has email::Lorem@ipsum.org]]
+* Has temperature: [[Has temperature::100 °C]]
+* Has wattage: [[Has wattage::9001]], [[Has wattage::9002 W]], [[Has wattage::10 kW]]
+* Has telephone number: [[Has telephone number::+1-201-555-0123]]
+* Has record: [[Has record::Lorem ipsum; closed]]
+* Has status: [[Has status::open]]
+* Has boolean: [[Has boolean::true]]
+
+{{#subobject:
+ |Has page={{PAGENAME}}
+ |Has number=1111
+ |Has quantity=25 sqmi
+ |Has date=January 4, 2010 7:00 pm
+ |Has Url=http://example.org/some/
+ |Has annotation uri=http://example.org/foaf.rdf
+ |Has email=Lorem@example.org
+ |Has temperature=100 °F
+ |Has wattage=42
+ |Has wattage=42 hp
+ |Has telephone number=+1-201-555-5555
+ |Has record=Lorem enim; closed
+ |Has status=closed
+ |Has boolean=false
+}}
+
+[[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Lorem Ipsum</title>
+ <ns>0</ns>
+ <id>600</id>
+ <sha1>94lztkh4kgb0mvjr87iyjfq4iv7ltlh</sha1>
+ <revision>
+ <id>1400</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="979">#REDIRECT [[Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Lorem ipsum</title>
+ <ns>14</ns>
+ <id>496</id>
+ <sha1>sir97j6uzt9ev2uyhaz1aj4i3spogih</sha1>
+ <revision>
+ <id>1355</id>
+ <timestamp>2014-04-04T22:29:18Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="17">[[Category:Main]]</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-002.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-002.xml
new file mode 100644
index 00000000..eac01775
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/Fixtures/import-002.xml
@@ -0,0 +1,214 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Lorem donec</title>
+ <ns>0</ns>
+ <id>1490</id>
+ <sha1>94lztkh4kgb0mvjr87iyjfq4iv7ltlh</sha1>
+ <revision>
+ <id>1550</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="979">
+* Has page: [[Has page::{{PAGENAME}}]]
+* Has number: [[Has number::1001]]
+* Has quantity: [[Has quantity::10.25 km²]]
+* Has date: [[Has date::1 Jan 2014]]
+* Has Url: [[Has Url::http://loremipsum.org/]]
+* Has annotation uri: [[Has annotation uri::http://loremipsum.org/foaf.rdf]]
+* Has email: [[Has email::Lorem@ipsum.org]]
+* Has temperature: [[Has temperature::100 °C]]
+* Has wattage: [[Has wattage::9001]], [[Has wattage::9002 W]], [[Has wattage::10 kW]]
+* Has telephone number: [[Has telephone number::+1-201-555-0123]]
+* Has record: [[Has record::Lorem ipsum; closed]]
+* Has status: [[Has status::open]]
+* Has boolean: [[Has boolean::true]]
+
+[[Category:Lorem donec]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Lorem enim</title>
+ <ns>0</ns>
+ <id>1493</id>
+ <sha1>94lztkh4kgb0mvjr87iyjfq4iv7ltlh</sha1>
+ <revision>
+ <id>1558</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="979">
+{{#subobject:
+ |Has page={{PAGENAME}}
+ |Has number=1111
+ |Has quantity=25 sqmi
+ |Has date=January 4, 2010 7:00 pm
+ |Has Url=http://example.org/some/
+ |Has annotation uri=http://example.org/foaf.rdf
+ |Has email=Lorem@example.org
+ |Has temperature=100 °F
+ |Has wattage=42
+ |Has wattage=42 hp
+ |Has telephone number=+1-201-555-5555
+ |Has record=Lorem enim; closed
+ |Has status=closed
+ |Has boolean=false
+}}
+
+[[Category:Lorem enim]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Template:Laoreet tortor</title>
+ <ns>10</ns>
+ <id>1600</id>
+ <sha1>c68evl9y2r71xng73mzd5z4c2u72a8h</sha1>
+ <revision>
+ <id>1601</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="494">&lt;includeonly&gt;
+{{#set:
+ |Has page={{{Has page}}}
+ |Has number={{{Has number}}}
+ |Has quantity={{{Has quantity}}}
+ |Has date={{{Has date}}}
+ |Has Url={{{Has Url}}}
+ |Has annotation uri={{{Has annotation uri}}}
+ |Has email={{{Has email}}}
+ |Has temperature={{{Has temperature}}}
+ |Has wattage={{{Has wattage}}}
+ |Has telephone number={{{Has telephone number}}}
+ |Has record={{{Has record}}}
+ |Has status={{{Has status}}}
+ |Has boolean={{{Has boolean}}}
+}}
+[[Category:Laoreet tortor]]&lt;/includeonly&gt;</text>
+ </revision>
+ </page>
+ <page>
+ <title>Lorem sit</title>
+ <ns>0</ns>
+ <id>1610</id>
+ <sha1>0rqia1jo6xts3vfzow5e2ulxapdo039</sha1>
+ <revision>
+ <id>1611</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="431">{{Laoreet tortor
+ |Has page={{PAGENAME}}
+ |Has number=1111
+ |Has quantity=25 sqmi
+ |Has date=January 4, 2010 7:00 pm
+ |Has Url=http://example.org/some/
+ |Has annotation uri=http://example.org/foaf.rdf
+ |Has email=Lorem@example.org
+ |Has temperature=100 °F
+ |Has wattage=42
+ |Has wattage=42 hp
+ |Has telephone number=+1-201-555-5555
+ |Has record=Lorem enim; closed
+ |Has status=closed
+ |Has boolean=false
+}}
+
+[[Category:lorem sit]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Lorem tempor</title>
+ <ns>0</ns>
+ <id>1620</id>
+ <sha1>0rqia1jo6xts3vfzow5e2ulxapdo039</sha1>
+ <revision>
+ <id>1621</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="431">{{#ask: [[Category:Lorem sit]][[Has page::+]]
+ |?Has page
+ |?Has number
+ |?Has quantity
+ |?Has date
+ |?Has Url
+ |?Has annotation uri
+ |?Has email
+ |?Has temperature
+ |?Has wattage
+ |limit=50
+}}
+
+{{#ask: [[Category:Lorem tortor]][[Has number::+]]
+ |?Has page
+ |?Has number
+ |?Has quantity
+ |?Has date
+ |?Has Url
+ |?Has annotation uri
+ |?Has email
+ |?Has temperature
+ |?Has wattage
+ |limit=50
+}}
+
+{{#ask: [[Category:Lorem enim]][[Has date::+]]
+ |?Has page
+ |?Has number
+ |?Has quantity
+ |?Has date
+ |?Has Url
+ |?Has annotation uri
+ |?Has email
+ |?Has temperature
+ |?Has wattage
+ |limit=50
+}}</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/JobQueueBenchmarkRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/JobQueueBenchmarkRunner.php
new file mode 100644
index 00000000..650d027c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/JobQueueBenchmarkRunner.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+use RuntimeException;
+use SMW\MediaWiki\JobFactory;
+use SMW\Tests\Utils\Runners\JobQueueRunner;
+use Title;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class JobQueueBenchmarkRunner implements BenchmarkReporter {
+
+ /**
+ * @var JobFactory
+ */
+ private $jobFactory;
+
+ /**
+ * @var JobQueueRunner
+ */
+ private $jobQueueRunner;
+
+ /**
+ * @var Benchmarker
+ */
+ private $benchmarker;
+
+ /**
+ * @var array
+ */
+ private $benchmarkReport = [];
+
+ /**
+ * @var string
+ */
+ private $testCaseLocation;
+
+ /**
+ * @since 2.5
+ *
+ * @param JobFactory $jobFactory
+ * @param JobQueueRunner $jobQueueRunner
+ * @param Benchmarker $benchmarker
+ */
+ public function __construct( JobFactory $jobFactory, JobQueueRunner $jobQueueRunner, Benchmarker $benchmarker ) {
+ $this->jobFactory = $jobFactory;
+ $this->jobQueueRunner = $jobQueueRunner;
+ $this->benchmarker = $benchmarker;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array
+ */
+ public function getBenchmarkReport() {
+ return $this->benchmarkReport;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $case
+ */
+ public function run( array $case ) {
+
+ $this->benchmarkReport = [];
+ $this->benchmarker->clear();
+
+ if ( !isset( $case['job'] ) ) {
+ throw new RuntimeException( 'No job name is available.' );
+ }
+
+ if ( !isset( $case['repetitionCount'] ) ) {
+ throw new RuntimeException( 'No repetitionCount is available.' );
+ }
+
+ $job = $this->jobFactory->newByType(
+ $case['job'],
+ Title::newFromText( __METHOD__ . $case['job'] )
+ );
+
+ $job->insert();
+
+ $this->doRunJob( $case );
+ }
+
+ private function doRunJob( array $case ) {
+
+ $this->jobQueueRunner->setType( $case['job'] );
+ $memoryBefore = memory_get_peak_usage( false );
+
+ for ( $i = 0; $i < $case['repetitionCount']; $i++ ) {
+
+ $start = microtime( true );
+
+ $this->jobQueueRunner->run();
+
+ $this->benchmarker->addBenchmarkPoint(
+ microtime( true ) - $start
+ );
+ }
+
+ $this->benchmarkReport = [
+ 'type' => $case['type'],
+ 'case' => $case['job'],
+ 'repetitionCount' => $case['repetitionCount'],
+ 'memory' => memory_get_peak_usage( false ) - $memoryBefore,
+ 'time' => [
+ 'sum' => $this->benchmarker->getSum(),
+ 'mean' => $this->benchmarker->getMean(),
+ 'sd' => $this->benchmarker->getStandardDeviation(),
+ 'norm' => $this->benchmarker->getNormalizedValueBy( $case['repetitionCount'] )
+ ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/MaintenanceBenchmarkRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/MaintenanceBenchmarkRunner.php
new file mode 100644
index 00000000..5299fba4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/MaintenanceBenchmarkRunner.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+use RuntimeException;
+use SMW\Tests\Utils\Runners\RunnerFactory;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class MaintenanceBenchmarkRunner implements BenchmarkReporter {
+
+ /**
+ * @var RunnerFactory
+ */
+ private $runnerFactory;
+
+ /**
+ * @var Benchmarker
+ */
+ private $benchmarker;
+
+ /**
+ * @var array
+ */
+ private $benchmarkReport = [];
+
+ /**
+ * @since 2.5
+ *
+ * @param RunnerFactory $runnerFactory
+ * @param Benchmarker $benchmarker
+ */
+ public function __construct( RunnerFactory $runnerFactory, Benchmarker $benchmarker ) {
+ $this->runnerFactory = $runnerFactory;
+ $this->benchmarker = $benchmarker;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array
+ */
+ public function getBenchmarkReport() {
+ return $this->benchmarkReport;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $case
+ */
+ public function run( array $case ) {
+
+ $this->benchmarkReport = [];
+ $this->benchmarker->clear();
+
+ if ( !isset( $case['script'] ) ) {
+ throw new RuntimeException( 'Script name is not available.' );
+ }
+
+ if ( !isset( $case['repetitionCount'] ) ) {
+ throw new RuntimeException( 'No repetitionCount is available.' );
+ }
+
+ if ( !isset( $case['options'] ) ) {
+ throw new RuntimeException( 'No options are available.' );
+ }
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner(
+ $case['script']
+ );
+
+ $maintenanceRunner->setQuiet();
+ $maintenanceRunner->setOptions( $case['options'] );
+
+ $this->doRunMaintenance( $maintenanceRunner, $case );
+ }
+
+ private function doRunMaintenance( $maintenanceRunner, array $case ) {
+
+ $memoryBefore = memory_get_peak_usage( false );
+
+ for ( $i = 0; $i < $case['repetitionCount']; $i++ ) {
+
+ $start = microtime( true );
+
+ $maintenanceRunner->run();
+
+ $this->benchmarker->addBenchmarkPoint(
+ microtime( true ) - $start
+ );
+ }
+
+ $this->benchmarkReport = [
+ 'type' => $case['type'],
+ 'case' => $case['script'],
+ 'repetitionCount' => $case['repetitionCount'],
+ 'memory' => memory_get_peak_usage( false ) - $memoryBefore,
+ 'time' => [
+ 'sum' => $this->benchmarker->getSum(),
+ 'mean' => $this->benchmarker->getMean(),
+ 'sd' => $this->benchmarker->getStandardDeviation(),
+ 'norm' => $this->benchmarker->getNormalizedValueBy( $case['repetitionCount'] )
+ ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageContentCopyBenchmarkRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageContentCopyBenchmarkRunner.php
new file mode 100644
index 00000000..57154279
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageContentCopyBenchmarkRunner.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+use RuntimeException;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Tests\Utils\PageReader;
+use Title;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PageContentCopyBenchmarkRunner {
+
+ /**
+ * @var PageImportBenchmarkRunner
+ */
+ private $pageImportBenchmarkRunner;
+
+ /**
+ * @var Benchmarker
+ */
+ private $benchmarker;
+
+ /**
+ * @var PageCreator
+ */
+ private $pageCreator;
+
+ /**
+ * @var PageReader
+ */
+ private $pageReader;
+
+ /**
+ * @var array
+ */
+ private $benchmarkReport = [];
+
+ /**
+ * @var integer|count
+ */
+ private $copyCount = null;
+
+ /**
+ * @since 2.5
+ *
+ * @param PageImportBenchmarkRunner $pageImportBenchmarkRunner
+ * @param Benchmarker $benchmarker
+ * @param PageCreator $pageCreator
+ * @param PageReader $pageReader
+ */
+ public function __construct( PageImportBenchmarkRunner $pageImportBenchmarkRunner, Benchmarker $benchmarker, PageCreator $pageCreator, PageReader $pageReader ) {
+ $this->pageImportBenchmarkRunner = $pageImportBenchmarkRunner;
+ $this->benchmarker = $benchmarker;
+ $this->pageCreator = $pageCreator;
+ $this->pageReader = $pageReader;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array
+ */
+ public function getBenchmarkReport() {
+ return $this->benchmarkReport;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param integer|null $copyCount
+ */
+ public function setCopyCount( $copyCount = null ) {
+ $this->copyCount = $copyCount;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $case
+ */
+ public function run( array $case ) {
+
+ $this->benchmarkReport = [];
+ $this->benchmarker->clear();
+ $start = microtime( true );
+
+ $this->pageImportBenchmarkRunner->run( $case );
+ $importBenchmarkReport = $this->pageImportBenchmarkRunner->getBenchmarkReport();
+
+ if ( !isset( $case['copyFrom'] ) ) {
+ throw new RuntimeException( 'Copy title is not available.' );
+ }
+
+ if ( !isset( $case['copyCount'] ) ) {
+ throw new RuntimeException( 'Copy count is not available.' );
+ }
+
+ $copyFrom = Title::newFromText( $case['copyFrom'] );
+
+ if ( !$copyFrom->exists() ) {
+ throw new RuntimeException( $case['copyFrom'] . ' is not available or readable for the copy process.' );
+ }
+
+ if ( !$this->canOverrideCount( $case ) ) {
+ $this->copyCount = $case['copyCount'];
+ }
+
+ $copyMemory = $this->doCopy( $copyFrom, $case );
+
+ $this->benchmarkReport = [
+ 'type' => $case['type'],
+ 'source' => $case['name'],
+ 'import' => [
+ 'memory' => $importBenchmarkReport['memory'],
+ 'time' => $importBenchmarkReport['time']
+ ],
+ 'copy' => [
+ 'copyFrom' => $case['copyFrom'],
+ 'copyCount' => $this->copyCount,
+ 'memory' => $copyMemory,
+ 'time' => [
+ 'sum' => $this->benchmarker->getSum(),
+ 'mean' => $this->benchmarker->getMean(),
+ 'sd' => $this->benchmarker->getStandardDeviation(),
+ 'norm' => $this->benchmarker->getNormalizedValueBy( $this->copyCount )
+ ]
+ ],
+ 'time' => microtime( true ) - $start
+ ];
+ }
+
+ private function doCopy( $copyFrom, array $case ) {
+
+ $copyText = $this->pageReader->getContentAsText( $copyFrom );
+ $copyName = 'BenchmarkCopy-' . $copyFrom->getText();
+
+ $memoryBefore = memory_get_peak_usage( false );
+
+ for ( $i = 0; $i < $this->copyCount; $i++ ) {
+
+ $start = microtime( true );
+
+ $this->pageCreator->createPage(
+ Title::newFromText( $copyName . '-' . $i ),
+ $copyText
+ );
+
+ $this->benchmarker->addBenchmarkPoint( microtime( true ) - $start );
+ }
+
+ return memory_get_peak_usage( false ) - $memoryBefore;
+ }
+
+ private function canOverrideCount( $case ) {
+ return isset( $case['canOverrideCopyCount'] ) && $case['canOverrideCopyCount'] && $this->copyCount !== null;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageEditCopyBenchmarkRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageEditCopyBenchmarkRunner.php
new file mode 100644
index 00000000..91fe7f31
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageEditCopyBenchmarkRunner.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+use RuntimeException;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Tests\Utils\PageReader;
+use Title;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PageEditCopyBenchmarkRunner {
+
+ /**
+ * @var PageImportBenchmarkRunner
+ */
+ private $pageImportBenchmarkRunner;
+
+ /**
+ * @var Benchmarker
+ */
+ private $benchmarker;
+
+ /**
+ * @var PageCreator
+ */
+ private $pageCreator;
+
+ /**
+ * @var PageReader
+ */
+ private $pageReader;
+
+ /**
+ * @var array
+ */
+ private $benchmarkReport = [];
+
+ /**
+ * @var integer|count
+ */
+ private $editRepetitionCount = null;
+
+ /**
+ * @since 2.5
+ *
+ * @param PageImportBenchmarkRunner $pageImportBenchmarkRunner
+ * @param Benchmarker $benchmarker
+ * @param PageCreator $pageCreator
+ * @param PageReader $pageReader
+ */
+ public function __construct( PageImportBenchmarkRunner $pageImportBenchmarkRunner, Benchmarker $benchmarker, PageCreator $pageCreator, PageReader $pageReader ) {
+ $this->pageImportBenchmarkRunner = $pageImportBenchmarkRunner;
+ $this->benchmarker = $benchmarker;
+ $this->pageCreator = $pageCreator;
+ $this->pageReader = $pageReader;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array
+ */
+ public function getBenchmarkReport() {
+ return $this->benchmarkReport;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param integer|null $copyCount
+ */
+ public function setEditRepetitionCount( $editRepetitionCount = null ) {
+ $this->editRepetitionCount = $editRepetitionCount;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $case
+ */
+ public function run( array $case ) {
+
+ $this->benchmarkReport = [];
+ $this->benchmarker->clear();
+
+ $start = microtime( true );
+
+ $this->pageImportBenchmarkRunner->run( $case );
+ $importBenchmarkReport = $this->pageImportBenchmarkRunner->getBenchmarkReport();
+
+ if ( !isset( $case['edit'] ) || !is_array( $case['edit'] ) ) {
+ throw new RuntimeException( 'Edit title is not available.' );
+ }
+
+ if ( !isset( $case['editRepetitionCount'] ) ) {
+ throw new RuntimeException( 'editRepetitionCount is not available.' );
+ }
+
+ if ( !$this->canOverrideCount( $case ) ) {
+ $this->editRepetitionCount = $case['editRepetitionCount'];
+ }
+
+ $editReports = [];
+
+ foreach ( $case['edit'] as $title ) {
+
+ $editTitle = Title::newFromText( $title );
+
+ if ( !$editTitle->exists() ) {
+ throw new RuntimeException( $title . ' is not available or readable for the edit process.' );
+ }
+
+ $editReports[$title] = $this->doEdit( $editTitle, $case );
+ }
+
+ $this->benchmarkReport = [
+ 'type' => $case['type'],
+ 'source' => $case['name'],
+ 'import' => [
+ 'memory' => $importBenchmarkReport['memory'],
+ 'time' => $importBenchmarkReport['time']
+ ],
+ 'editTask' => $editReports,
+ 'time' => microtime( true ) - $start
+ ];
+ }
+
+ private function doEdit( $editTitle, array $case ) {
+
+ $copyText = $this->pageReader->getContentAsText( $editTitle );
+ $this->benchmarker->clear();
+
+ $memoryBefore = memory_get_peak_usage( false );
+
+ for ( $i = 0; $i < $this->editRepetitionCount; $i++ ) {
+
+ $start = microtime( true );
+
+ $this->pageCreator->createPage(
+ $editTitle,
+ $copyText
+ );
+
+ $this->benchmarker->addBenchmarkPoint( microtime( true ) - $start );
+ }
+
+ return [
+ 'editRepetitionCount' => $this->editRepetitionCount,
+ "memory" => memory_get_peak_usage( false ) - $memoryBefore,
+ "time" => [
+ 'sum' => $this->benchmarker->getSum(),
+ 'mean' => $this->benchmarker->getMean(),
+ 'sd' => $this->benchmarker->getStandardDeviation(),
+ 'norm' => $this->benchmarker->getNormalizedValueBy( $this->editRepetitionCount )
+ ]
+ ];
+ }
+
+ private function canOverrideCount( $case ) {
+ return isset( $case['canOverrideEditCount'] ) && $case['canOverrideEditCount'] && $this->editRepetitionCount !== null;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageImportBenchmarkRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageImportBenchmarkRunner.php
new file mode 100644
index 00000000..758dd7f8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/PageImportBenchmarkRunner.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+use RuntimeException;
+use SMW\Tests\Utils\Runners\XmlImportRunner;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PageImportBenchmarkRunner implements BenchmarkReporter {
+
+ /**
+ * @var XmlImportRunner
+ */
+ private $xmlImportRunner;
+
+ /**
+ * @var Benchmarker
+ */
+ private $benchmarker;
+
+ /**
+ * @var array
+ */
+ private $benchmarkReport = [];
+
+ /**
+ * @var string
+ */
+ private $testCaseLocation;
+
+ /**
+ * @since 2.5
+ *
+ * @param XmlImportRunner $xmlImportRunner
+ * @param Benchmarker $benchmarker
+ */
+ public function __construct( XmlImportRunner $xmlImportRunner, Benchmarker $benchmarker ) {
+ $this->xmlImportRunner = $xmlImportRunner;
+ $this->benchmarker = $benchmarker;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $testCaseLocation
+ */
+ public function setTestCaseLocation( $testCaseLocation ) {
+ $this->testCaseLocation = $testCaseLocation;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array
+ */
+ public function getBenchmarkReport() {
+ return $this->benchmarkReport;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $case
+ */
+ public function run( array $case ) {
+
+ $this->benchmarkReport = [];
+ $this->benchmarker->clear();
+
+ if ( !isset( $case['importFrom'] ) ) {
+ throw new RuntimeException( 'No import file is available.' );
+ }
+
+ $file = $this->testCaseLocation . $case['importFrom'];
+
+ if ( !is_readable( $file ) ) {
+ throw new RuntimeException( $file . ' as import file is not available.' );
+ }
+
+ $ext = pathinfo( $file, PATHINFO_EXTENSION );
+
+ switch ( $ext ) {
+ case 'xml':
+ return $this->doXmlImport( $file, $case );
+ break;
+ default:
+ # code...
+ break;
+ }
+ }
+
+ private function doXmlImport( $file, array $case ) {
+
+ $this->xmlImportRunner->setFile( $file );
+ $this->xmlImportRunner->setVerbose( true );
+
+ $memoryBefore = memory_get_peak_usage( false );
+
+ if ( !$this->xmlImportRunner->run() ) {
+ $this->xmlImportRunner->reportFailedImport();
+ }
+
+ $this->benchmarkReport = [
+ 'type' => $case['type'],
+ 'source' => $case['name'],
+ 'memory' => memory_get_peak_usage( false ) - $memoryBefore,
+ 'time' => [
+ 'sum' => $this->xmlImportRunner->getElapsedImportTimeInSeconds()
+ ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/QueryBenchmarkRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/QueryBenchmarkRunner.php
new file mode 100644
index 00000000..2ff457dd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/QueryBenchmarkRunner.php
@@ -0,0 +1,169 @@
+<?php
+
+namespace SMW\Tests\Benchmark;
+
+use RuntimeException;
+use SMW\DIProperty;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Store;
+use SMWPropertyValue as PropertyValue;
+use SMWQuery as Query;
+use SMWQueryParser as QueryParser;
+use Title;
+
+/**
+ * @group semantic-mediawiki-benchmark
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QueryBenchmarkRunner implements BenchmarkReporter {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var QueryParser
+ */
+ private $queryParser;
+
+ /**
+ * @var Benchmarker
+ */
+ private $benchmarker;
+
+ /**
+ * @var array
+ */
+ private $benchmarkReport = [];
+
+ /**
+ * @since 2.5
+ *
+ * @param Store $store
+ * @param QueryParser $queryParser
+ * @param Benchmarker $benchmarker
+ */
+ public function __construct( Store $store, QueryParser $queryParser, Benchmarker $benchmarker ) {
+ $this->store = $store;
+ $this->queryParser = $queryParser;
+ $this->benchmarker = $benchmarker;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array
+ */
+ public function getBenchmarkReport() {
+ return $this->benchmarkReport;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $case
+ */
+ public function run( array $case ) {
+
+ $this->benchmarkReport = [];
+ $this->benchmarker->clear();
+
+ if ( !isset( $case['query'] ) && !is_array( $case['query'] ) ) {
+ throw new RuntimeException( 'Query specification is not available.' );
+ }
+
+ if ( !isset( $case['repetitionCount'] ) ) {
+ throw new RuntimeException( 'repetitionCount is not available.' );
+ }
+
+ $start = microtime( true );
+ $queryReports = [];
+
+ $queryReports['count'] = $this->doQuery(
+ $case, $this->createQuery( $case, Query::MODE_COUNT )
+ );
+
+ $queryReports['instance'] = $this->doQuery(
+ $case, $this->createQuery( $case, Query::MODE_INSTANCES )
+ );
+
+ $this->benchmarkReport = [
+ 'type' => $case['type'],
+ 'note' => $case['query']['condition'] . ( isset( $case['note'] ) ? ' (' . $case['note'] . ')' : '' ),
+ 'query' => $queryReports,
+ 'time' => microtime( true ) - $start
+ ];
+ }
+
+ private function doQuery( array $case, $query ) {
+
+ $this->benchmarker->clear();
+
+ $memoryBefore = memory_get_peak_usage( false );
+
+ for ( $i = 0; $i < $case['repetitionCount']; $i++ ) {
+
+ $start = microtime( true );
+
+ $queryResult = $this->store->getQueryResult( $query );
+
+ $this->benchmarker->addBenchmarkPoint( microtime( true ) - $start );
+ }
+
+ $count = $query->querymode === Query::MODE_COUNT ? $queryResult->getCountValue() : $queryResult->getCount();
+ $columnCount = $queryResult->getColumnCount();
+
+ return [
+ 'rowCount' => $count,
+ 'columnCount' => $columnCount,
+ 'repetitionCount' => $case['repetitionCount'],
+ "memory" => memory_get_peak_usage( false ) - $memoryBefore,
+ "time" => [
+ 'sum' => $this->benchmarker->getSum(),
+ 'mean' => $this->benchmarker->getMean(),
+ 'sd' => $this->benchmarker->getStandardDeviation(),
+ 'norm' => $this->benchmarker->getNormalizedValueBy( $case['repetitionCount'] )
+ ]
+ ];
+ }
+
+ private function createQuery( array $case, $mode, array $printouts = [] ) {
+
+ $description = $this->queryParser->getQueryDescription(
+ $case['query']['condition']
+ );
+
+ foreach ( $case['query']['printouts'] as $printout ) {
+ $property = DIProperty::newFromUserLabel( $printout );
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $property );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+ }
+
+ $query = new Query(
+ $description
+ );
+
+ $query->setUnboundlimit(
+ isset( $case['query']['parameters']['limit'] ) ? $case['query']['parameters']['limit'] : 500
+ );
+
+ $query->setOffset(
+ isset( $case['query']['parameters']['offset'] ) ? $case['query']['parameters']['offset'] : 0
+ );
+
+ $query->setQueryMode( $mode );
+
+ return $query;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/README.md b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/README.md
new file mode 100644
index 00000000..f19bb949
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/README.md
@@ -0,0 +1,56 @@
+Benchmark tests are to use `PHPUnit` as integration platform and do not always
+represent the best tool for a performance comparison (as it depends on environmental
+factors such as hardware and software constraints which might not be under the
+control of the tester) but it can help to identify performance regressions among
+newly introduced features that run with the same environmental specification.
+
+Benchmarks are not performed in isolation and therefore run in concert with the
+`MediaWiki` infrastructure to determine the overall performance impact during
+execution.
+
+When using `git`, it is relatively easy to run tests and see if a change
+introduces a significant regression or improvement in terms of performance over
+the existing `master` branch by comparing test results of the `master` against
+a `feature` branch.
+
+## Designing benchmark tests
+
+The definition of what benchmarks are executed is specified by a `JSONScript`
+found in the `TestCases` directory. Supported types are:
+
+- `import` to import data from an external source
+- `contentCopy` copy content from an internal source
+- `editCopy` edit content from an internal source
+- `job` running selected jobs
+- `maintenance` running selected maintenance scripts
+- `query` executing `#ask` queries
+
+## Running benchmark tests
+
+Running `composer benchmark` from the Semantic MediaWiki base directory should
+output something similar to what can be seen below.
+
+```
+- mediawiki: "1.28.0-alpha"
+- semantic-mediawiki: "2.5.0-alpha"
+- environment: {"store":"SMWSQLStore3","db":"mysql"}
+- benchmarks
+- 35a205a6fa1db2cda4c484d3007953b3
+ - type: "import"
+ - source: "import-001.xml"
+ - memory: 5564360
+ - time: {"sum":5.9888241}
+- 054543b5702e6fcbccafd00bf6dd27ac
+ - type: "contentCopy"
+ - source: "import-001.xml"
+ - import
+ - memory: 351392
+ - time: {"sum":0.900929}
+ - copy
+ - copyFrom: "Lorem ipsum"
+ - copyCount: 10
+ - memory: 75056
+ - time: {"sum":7.9295225,"mean":0.7929523,"sd":0.1008703,"norm":0.0792952}
+ - time: 8.8402690887451
+
+```
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-001.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-001.json
new file mode 100644
index 00000000..f50e75c7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-001.json
@@ -0,0 +1,53 @@
+{
+ "description": "Standard import and rebuild benchmarks",
+ "tests": [
+ {
+ "type": "import",
+ "name": "import-001.xml",
+ "importFrom": "/../Fixtures/import-001.xml"
+ },
+ {
+ "type": "contentCopy",
+ "name": "import-001.xml",
+ "importFrom": "/../Fixtures/import-001.xml",
+ "copyFrom": "Lorem ipsum",
+ "canOverrideCopyCount": true,
+ "copyCount": 1000
+ },
+ {
+ "type": "editCopy",
+ "name": "import-002.xml",
+ "importFrom": "/../Fixtures/import-002.xml",
+ "edit": [
+ "Lorem ipsum",
+ "Lorem donec",
+ "Lorem enim",
+ "Lorem sit",
+ "Lorem tempor"
+ ],
+ "canOverrideEditCount": true,
+ "editRepetitionCount": 50
+ },
+ {
+ "type": "job",
+ "job": "SMW\\RefreshJob",
+ "repetitionCount": 1
+ },
+ {
+ "type": "job",
+ "job": "SMW\\UpdateJob",
+ "repetitionCount": 1
+ },
+ {
+ "type": "maintenance",
+ "script": "rebuildData",
+ "options": {
+ "f": true
+ },
+ "repetitionCount": 1
+ }
+ ],
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-002.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-002.json
new file mode 100644
index 00000000..bbcfc186
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/TestCases/b-002.json
@@ -0,0 +1,186 @@
+{
+ "description": "Query related benchmarks",
+ "tests": [
+ {
+ "type": "query",
+ "note": "Select all possible entities for the MAIN namespace",
+ "query": {
+ "condition": "[[:+]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": []
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Select entities for a specific category",
+ "query": {
+ "condition": "[[Category: Lorem ipsum]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": []
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Category and namespace search conjunction",
+ "query": {
+ "condition": "[[Category: Lorem ipsum]] AND [[Property:+]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": []
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Simple property wildcard value search including subobjects",
+ "query": {
+ "condition": "[[Has Url::+]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has Url"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Simple property wildcard value search including subobjects",
+ "query": {
+ "condition": "[[Has quantity::+]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has quantity"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Simple property wildcard value search that does not include subobjects",
+ "query": {
+ "condition": "[[Has Url::+]][[Category: Lorem ipsum]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has Url"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Distinct value search that only includes subobjects",
+ "query": {
+ "condition": "[[Has number::1111]][[Has quantity::25 sqmi]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has number",
+ "Has quantity"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Distinct value disjuntived search that only includes subobjects",
+ "query": {
+ "condition": "[[Has number::1111]] OR [[Has quantity::25 sqmi]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has number",
+ "Has quantity"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Distinct value search that does not include subobjects",
+ "query": {
+ "condition": "[[Has date::1 Jan 2014]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has date"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Wildcard value search that does not include subobjects",
+ "query": {
+ "condition": "[[Has text::~Lorem ipsum dolor*]][[Category: Lorem ipsum]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has text"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Distinct value search on subobject entities",
+ "query": {
+ "condition": "[[Has subobject.Has temperature::100 °F]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has date",
+ "Has quantity",
+ "Has date",
+ "Has Url",
+ "Has annotation uri",
+ "Has wattage",
+ "Has temperature",
+ "Has text"
+ ]
+ },
+ "repetitionCount": 5
+ },
+ {
+ "type": "query",
+ "note": "Complex disjuntived query",
+ "query": {
+ "condition": "<q>[[Has page.Has number::1001]][[Has page.Has telephone number::+1-201-555-0123]]</q> OR [[Has subobject.Has temperature::100 °F]][[Category:!Lorem enim]]",
+ "parameters": {
+ "limit": 500
+ },
+ "printouts": [
+ "Has date",
+ "Has quantity",
+ "Has date",
+ "Has Url",
+ "Has annotation uri",
+ "Has wattage",
+ "Has temperature",
+ "Has text"
+ ]
+ },
+ "repetitionCount": 5
+ }
+ ],
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/phpunit.quick.xml.dist b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/phpunit.quick.xml.dist
new file mode 100644
index 00000000..59f26e7c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Benchmark/phpunit.quick.xml.dist
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="false"
+ backupStaticAttributes="false"
+ bootstrap="../../bootstrap.php"
+ cacheTokens="false"
+ colors="true"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ stopOnError="false"
+ stopOnFailure="false"
+ stopOnIncomplete="false"
+ stopOnSkipped="false"
+ beStrictAboutTestsThatDoNotTestAnything="true"
+ verbose="true">
+ <testsuites>
+ <testsuite name="semantic-mediawiki-benchmark">
+ <directory>../../phpunit/Benchmark</directory>
+ </testsuite>
+ </testsuites>
+ <groups>
+ <exclude>
+ <group>semantic-mediawiki-benchmark</group>
+ </exclude>
+ </groups>
+ <filter>
+ <whitelist addUncoveredFilesFromWhitelist="true">
+ <directory suffix=".php">src</directory>
+ <directory suffix=".php">includes</directory>
+ <directory suffix=".php">maintenance</directory>
+ </whitelist>
+ </filter>
+ <php>
+ <var name="smwgSemanticsEnabled" value="true"/>
+ <var name="smwgEnabledFulltextSearch" value="false"/>
+ <var name="benchmarkPageCopyCount" value="200"/>
+ <var name="benchmarkPageEditRepetitionCount" value="2"/>
+ </php>
+</phpunit>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/DatabaseTestCase.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/DatabaseTestCase.php
new file mode 100644
index 00000000..16a5d7cf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/DatabaseTestCase.php
@@ -0,0 +1,234 @@
+<?php
+
+namespace SMW\Tests;
+
+use RuntimeException;
+use SMW\ApplicationFactory;
+use SMW\NamespaceExaminer;
+use SMW\PropertyRegistry;
+use SMW\Settings;
+use SMW\StoreFactory;
+use SMW\Tests\Utils\Connection\TestDatabaseTableBuilder;
+use SMWExporter as Exporter;
+
+/**
+ * @group semantic-mediawiki
+ * @group mediawiki-database
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+abstract class DatabaseTestCase extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var TestEnvironment
+ */
+ protected $testEnvironment;
+
+ /**
+ * @var TestDatabaseTableBuilder
+ */
+ protected $testDatabaseTableBuilder;
+
+ /**
+ * @var array|null
+ */
+ protected $databaseToBeExcluded = null;
+
+ /**
+ * @var array|null
+ */
+ protected $storesToBeExcluded = null;
+
+ /**
+ * @var boolean
+ */
+ protected $destroyDatabaseTablesBeforeRun = false;
+
+ /**
+ * @var boolean
+ */
+ protected $destroyDatabaseTablesAfterRun = false;
+
+ /**
+ * @var boolean
+ */
+ protected $isUsableUnitTestDatabase = true;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->addConfiguration( 'smwgEnabledDeferredUpdate', false );
+
+ PropertyRegistry::clear();
+
+ $this->checkIfDatabaseCanBeUsedOtherwiseSkipTest();
+ $this->checkIfStoreCanBeUsedOtherwiseSkipTest();
+
+ ApplicationFactory::getInstance()->registerObject( 'Store', $this->getStore() );
+
+ ApplicationFactory::getInstance()->registerObject(
+ 'Cache',
+ ApplicationFactory::getInstance()->newCacheFactory()->newFixedInMemoryCache()
+ );
+
+ // Avoid surprise on revisions etc.
+ // @see MediaWikiTestCase::doLightweightServiceReset
+ $this->testEnvironment->resetMediaWikiService( 'MainObjectStash' );
+ $this->testEnvironment->resetMediaWikiService( 'LocalServerObjectCache' );
+ $this->testEnvironment->resetMediaWikiService( 'MainWANObjectCache' );
+
+ $this->testEnvironment->clearPendingDeferredUpdates();
+ }
+
+ protected function tearDown() {
+
+ // If setUp is skipped early this might not be initialized
+ if ( $this->testEnvironment !== null ) {
+ $this->testEnvironment->tearDown();
+ }
+
+ ApplicationFactory::clear();
+ NamespaceExaminer::clear();
+ PropertyRegistry::clear();
+ Settings::clear();
+ Exporter::getInstance()->clear();
+
+ parent::tearDown();
+ }
+
+ /**
+ * It is assumed that each test that makes use of the TestCase is requesting
+ * a "real" DB connection
+ *
+ * By default, the database tables are being re-used but it is possible to
+ * request a trear down so that the next test can rebuild the tables from
+ * scratch
+ */
+ public function run( \PHPUnit_Framework_TestResult $result = null ) {
+
+ $this->getStore()->clear();
+
+ $this->testDatabaseTableBuilder = TestDatabaseTableBuilder::getInstance(
+ $this->getStore()
+ );
+
+ $this->testDatabaseTableBuilder->removeAvailableDatabaseType(
+ $this->databaseToBeExcluded
+ );
+
+ $this->destroyDatabaseTables( $this->destroyDatabaseTablesBeforeRun );
+
+ try {
+ $this->testDatabaseTableBuilder->doBuild();
+ } catch ( RuntimeException $e ) {
+ $this->isUsableUnitTestDatabase = false;
+ }
+
+ parent::run( $result );
+
+ $this->destroyDatabaseTables( $this->destroyDatabaseTablesAfterRun );
+ }
+
+ protected function removeDatabaseTypeFromTest( $databaseToBeExcluded ) {
+ $this->databaseToBeExcluded = $databaseToBeExcluded;
+ }
+
+ protected function destroyDatabaseTablesAfterRun() {
+ $this->destroyDatabaseTablesAfterRun = true;
+ }
+
+ protected function getStore() {
+ return StoreFactory::getStore();
+ }
+
+ protected function setStoresToBeExcluded( array $storesToBeExcluded ) {
+ return $this->storesToBeExcluded = $storesToBeExcluded;
+ }
+
+ protected function skipTestForMediaWikiVersionLowerThan( $version, $message = '' ) {
+
+ if ( $message === '' ) {
+ $message = "This test is skipped for MediaWiki version {$GLOBALS['wgVersion']}";
+ }
+
+ if ( version_compare( $GLOBALS['wgVersion'], $version, '<' ) ) {
+ $this->markTestSkipped( $message );
+ }
+ }
+
+ protected function skipTestForDatabase( $excludedDatabase, $message = '' ) {
+
+ if ( is_string( $excludedDatabase ) ) {
+ $excludedDatabase = [ $excludedDatabase ];
+ }
+
+ if ( $message === '' ) {
+ $message = "Database was excluded and is not expected to support this test";
+ }
+
+ if ( in_array( $this->getDBConnection()->getType(), $excludedDatabase ) ) {
+ $this->markTestSkipped( $message );
+ }
+ }
+
+ protected function skipTestForStore( $excludeStore ) {
+
+ $store = get_class( $this->getStore() );
+
+ if ( $store == $excludeStore ) {
+ $this->markTestSkipped(
+ "{$store} was excluded and is not expected to support the test"
+ );
+ }
+ }
+
+ protected function getDBConnection() {
+ return $this->testDatabaseTableBuilder->getDBConnection();
+ }
+
+ protected function getConnectionProvider() {
+ return $this->testDatabaseTableBuilder->getConnectionProvider();
+ }
+
+ protected function isUsableUnitTestDatabase() {
+ return $this->isUsableUnitTestDatabase;
+ }
+
+ protected function checkIfDatabaseCanBeUsedOtherwiseSkipTest() {
+
+ if ( !$this->isUsableUnitTestDatabase ) {
+ $this->markTestSkipped(
+ "Database was excluded and is not expected to support the test"
+ );
+ }
+ }
+
+ protected function checkIfStoreCanBeUsedOtherwiseSkipTest() {
+
+ $store = get_class( $this->getStore() );
+
+ if ( in_array( $store, (array)$this->storesToBeExcluded ) ) {
+ $this->markTestSkipped(
+ "{$store} was excluded and is not expected to support the test"
+ );
+ }
+ }
+
+ private function destroyDatabaseTables( $destroyDatabaseTables ) {
+
+ if ( $this->isUsableUnitTestDatabase && $destroyDatabaseTables ) {
+ try {
+ $this->testDatabaseTableBuilder->doDestroy();
+ } catch ( \Exception $e ) { // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.CodeAnalysis.EmptyStatement
+ // Do nothing because an instance was not available
+ } // @codingStandardsIgnoreEnd
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/ExecutionTimeTestListener.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/ExecutionTimeTestListener.php
new file mode 100644
index 00000000..6d541b28
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/ExecutionTimeTestListener.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests;
+
+use Exception;
+use PHPUnit_Framework_AssertionFailedError;
+use PHPUnit_Framework_Test;
+use PHPUnit_Framework_TestListener;
+use PHPUnit_Framework_TestSuite;
+use PHPUnit_Framework_Warning;
+
+class ExecutionTimeTestListener implements PHPUnit_Framework_TestListener {
+
+ protected $testCollector = [];
+ protected $executionTimeThresholdInSeconds = 10;
+ protected $isEnabledToListen = true;
+
+ public function __construct( $isEnabledToListen, $executionTimeThresholdInSeconds ) {
+ $this->isEnabledToListen = $isEnabledToListen;
+ $this->executionTimeThresholdInSeconds = $executionTimeThresholdInSeconds;
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::startTest
+ */
+ public function startTest( PHPUnit_Framework_Test $test ) {
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::endTest
+ */
+ public function endTest( PHPUnit_Framework_Test $test, $length ) {
+ if ( $this->isEnabledToListen && ( $length > $this->executionTimeThresholdInSeconds ) ) {
+ $this->testCollector[$test->getName()] = round( $length, 3 );
+ }
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::addError
+ */
+ public function addError( PHPUnit_Framework_Test $test, Exception $e, $time ) {
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::addError
+ */
+ public function addWarning( PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time) {
+
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::addFailure
+ */
+ public function addFailure( PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time ) {
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::addError
+ */
+ public function addIncompleteTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::addRiskyTest
+ * @since 4.0.0
+ */
+ public function addRiskyTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::addSkippedTest
+ */
+ public function addSkippedTest( PHPUnit_Framework_Test $test, Exception $e, $time ) {
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::startTestSuite
+ */
+ public function startTestSuite( PHPUnit_Framework_TestSuite $suite ) {
+ }
+
+ /**
+ * @see PHPUnit_Framework_TestListener::endTestSuite
+ */
+ public function endTestSuite( PHPUnit_Framework_TestSuite $suite ) {
+ foreach ( $this->testCollector as $name => $length ) {
+ print ( "\n" . $suite->getName() . " {$name} ran for {$length} seconds" . "\n" );
+ unset( $this->testCollector[$name] );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/EncodingIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/EncodingIntegrationTest.php
new file mode 100644
index 00000000..34cdb918
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/EncodingIntegrationTest.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Hooks\BaseTemplateToolbox;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\BaseTemplateToolbox
+ * @covers \SMWInfolink
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-databaseless
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class EncodingIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider baseTemplateToolboxDataProvider
+ */
+ public function testBaseTemplateToolboxURLEncoding( $setup, $expected ) {
+
+ $toolbox = [];
+
+ foreach ( $setup['settings'] as $key => $value) {
+ ApplicationFactory::getInstance()->getSettings()->set( $key, $value );
+ }
+
+ $instance = new BaseTemplateToolbox(
+ ApplicationFactory::getInstance()->getNamespaceExaminer()
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgBrowseFeatures' => $setup['settings']['smwgBrowseFeatures']
+ ]
+ );
+
+ $instance->process( $setup['skinTemplate'], $toolbox );
+
+ $this->assertContains(
+ $expected,
+ $toolbox['smw-browse']['href']
+ );
+
+ ApplicationFactory::clear();
+ }
+
+ public function baseTemplateToolboxDataProvider() {
+
+ $specialName = str_replace( '%3A', ':',
+ \SMW\Encoder::encode( \SpecialPage::getTitleFor( 'Browse' )->getPrefixedText() )
+ );
+
+ $provider = [];
+
+ $provider[] = [ $this->newBaseTemplateToolboxSetup( '2013/11/05' ), "$specialName/:2013-2F11-2F05" ];
+ $provider[] = [ $this->newBaseTemplateToolboxSetup( '2013-06-30' ), "$specialName/:2013-2D06-2D30" ];
+ $provider[] = [ $this->newBaseTemplateToolboxSetup( '2013$06&30' ), "$specialName/:2013-2406-2630" ];
+ $provider[] = [ $this->newBaseTemplateToolboxSetup( '2013\Foo' ), "$specialName/:2013-5CFoo" ];
+
+ return $provider;
+ }
+
+ private function newBaseTemplateToolboxSetup( $text ) {
+
+ $settings = [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgBrowseFeatures' => SMW_BROWSE_TLINK
+ ];
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( Title::newFromText( $text, NS_MAIN ) ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'msg' )
+ ->will( $this->returnValue( $message ) );
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $skin ) );
+
+ $skinTemplate->data['isarticle'] = true;
+
+ return [ 'settings' => $settings, 'skinTemplate' => $skinTemplate ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/content.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/content.json
new file mode 100644
index 00000000..9dd4dc68
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/content.json
@@ -0,0 +1,26 @@
+{
+ "description": "Test import",
+ "import": [
+ {
+ "page": "Smw import foaf",
+ "namespace": "NS_MEDIAWIKI",
+ "contents": {
+ "importFrom": "foaf.txt"
+ },
+ "options": {
+ "canReplace": false
+ }
+ },
+ {
+ "page": "Foaf:knows",
+ "namespace": "SMW_NS_PROPERTY",
+ "contents": "* [[Imported from::foaf:knows]]",
+ "options": {
+ "canReplace": false
+ }
+ }
+ ],
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/foaf.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/foaf.txt
new file mode 100644
index 00000000..15106fc0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidTextContent/foaf.txt
@@ -0,0 +1,13 @@
+http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]
+ name|Type:Text
+ homepage|Type:URL
+ mbox|Type:Email
+ mbox_sha1sum|Type:Text
+ depiction|Type:URL
+ phone|Type:Text
+ Person|Category
+ Organization|Category
+ knows|Type:Page
+ member|Type:Page
+
+[[Category:Imported vocabulary]] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/content.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/content.json
new file mode 100644
index 00000000..932c3866
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/content.json
@@ -0,0 +1,14 @@
+{
+ "description": "Test import",
+ "import": [
+ {
+ "description": "Xml import",
+ "contents": {
+ "importFrom": "test.xml"
+ }
+ }
+ ],
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/test.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/test.xml
new file mode 100644
index 00000000..69da5694
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/Fixtures/ValidXmlContent/test.xml
@@ -0,0 +1,68 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.8/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.8/ http://www.mediawiki.org/xml/export-0.8.xsd" version="0.8" xml:lang="en">
+ <siteinfo>
+ <sitename>test</sitename>
+ <base>http://localhost:8080/test/index.php/Main_Page</base>
+ <generator>MediaWiki 1.23.9</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">test</namespace>
+ <namespace key="5" case="first-letter">test talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Property:ImportTest</title>
+ <ns>102</ns>
+ <id>4119</id>
+ <revision>
+ <id>10260</id>
+ <timestamp>2000-03-29T10:48:42Z</timestamp>
+ <contributor>
+ <username>Importer</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Number]]&quot;</comment>
+ <text xml:space="preserve" bytes="20">[[Has type::Number]]</text>
+ <sha1>kph48zlgloy5jxc3qmxgjzz2179e04c</sha1>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ </revision>
+ </page>
+ <page>
+ <title>ImportTest</title>
+ <ns>0</ns>
+ <id>4118</id>
+ <revision>
+ <id>10259</id>
+ <timestamp>2000-03-29T10:48:21Z</timestamp>
+ <contributor>
+ <username>Importer</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[ImportTest::123]]&quot;</comment>
+ <text xml:space="preserve" bytes="19">[[ImportTest::123]]</text>
+ <sha1>az827f6th4x9hr9udej643f9p13akgf</sha1>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/ImporterIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/ImporterIntegrationTest.php
new file mode 100644
index 00000000..635abc8f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Importer/ImporterIntegrationTest.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace SMW\Tests\Integration\Importer;
+
+use SMW\ApplicationFactory;
+use SMW\Tests\MwDBaseUnitTestCase;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ImporterIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $spyMessageReporter;
+ private $importerServiceFactory;
+ private $stringValidator;
+ private $fixtures;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+ $this->fixtures = __DIR__ . '/Fixtures';
+
+ $this->importerServiceFactory = ApplicationFactory::getInstance()->create( 'ImporterServiceFactory' );
+ $this->spyMessageReporter = $utilityFactory->newSpyMessageReporter();
+ $this->stringValidator = $utilityFactory->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testValidTextContent() {
+
+ $importer = $this->importerServiceFactory->newImporter(
+ $this->importerServiceFactory->newJsonContentIterator( [ $this->fixtures . '/ValidTextContent' ] )
+ );
+
+ $importer->setMessageReporter( $this->spyMessageReporter );
+ $importer->setReqVersion( 1 );
+
+ $importer->doImport();
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ 'Smw import foaf',
+ 'Foaf:knows'
+ ],
+ $this->spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testValidXmlContent() {
+
+ if ( !interface_exists( '\ImportSource' ) ) {
+ $this->markTestSkipped( "ImportSource interface is unknown (MW 1.25-)" );
+ }
+
+ $importer = $this->importerServiceFactory->newImporter(
+ $this->importerServiceFactory->newJsonContentIterator( [ $this->fixtures . '/ValidXmlContent' ] )
+ );
+
+ $importer->setMessageReporter( $this->spyMessageReporter );
+ $importer->setReqVersion( 1 );
+
+ $importer->doImport();
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ 'ImportTest'
+ ],
+ $this->spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/InterwikiDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/InterwikiDBIntegrationTest.php
new file mode 100644
index 00000000..d7c94f39
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/InterwikiDBIntegrationTest.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWExportController as ExportController;
+use SMWQuery as Query;
+use SMWRDFXMLSerializer as RDFXMLSerializer;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class InterwikiDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $stringValidator;
+ private $subjects = [];
+
+ private $pageCreator;
+ private $stringBuilder;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = UtilityFactory::getInstance();
+
+ $this->semanticDataFactory = $utilityFactory->newSemanticDataFactory();
+ $this->stringValidator = $utilityFactory->newValidatorFactory()->newStringValidator();
+
+ $this->pageCreator = $utilityFactory->newPageCreator();
+ $this->stringBuilder = $utilityFactory->newStringBuilder();
+
+ $this->queryResultValidator = $utilityFactory->newValidatorFactory()->newQueryResultValidator();
+ $this->queryParser = ApplicationFactory::getInstance()->newQueryParser();
+
+ // Manipulate the interwiki prefix on-the-fly
+ $GLOBALS['wgHooks']['InterwikiLoadPrefix'][] = function( $prefix, &$interwiki ) {
+
+ if ( $prefix !== 'iw-test' ) {
+ return true;
+ }
+
+ $interwiki = [
+ 'iw_prefix' => 'iw-test',
+ 'iw_url' => 'http://www.example.org/$1',
+ 'iw_api' => false,
+ 'iw_wikiid' => 'foo',
+ 'iw_local' => true,
+ 'iw_trans' => false,
+ ];
+
+ return false;
+ };
+ }
+
+ protected function tearDown() {
+
+ UtilityFactory::getInstance()->newPageDeleter()->doDeletePoolOfPages( $this->subjects );
+ unset( $GLOBALS['wgHooks']['InterwikiLoadPrefix'] );
+
+ parent::tearDown();
+ }
+
+ public function testRdfSerializationForInterwikiAnnotation() {
+
+ $this->stringBuilder
+ ->addString( '[[Has type::Page]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Use for interwiki annotation', SMW_NS_PROPERTY ) )
+ ->doEdit( $this->stringBuilder->getString() );
+
+ $this->stringBuilder
+ ->addString( '[[Use for interwiki annotation::Interwiki link]]' )
+ ->addString( '[[Use for interwiki annotation::iw-test:Interwiki link]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( __METHOD__ ) )
+ ->doEdit( $this->stringBuilder->getString() );
+
+ $output = $this->fetchSerializedRdfOutputFor(
+ [ __METHOD__ ]
+ );
+
+ $expectedOutputContent = [
+ '<property:Use_for_interwiki_annotation rdf:resource="&wiki;Interwiki_link"/>',
+ '<property:Use_for_interwiki_annotation rdf:resource="&wiki;iw-2Dtest-3AInterwiki_link"/>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expectedOutputContent,
+ $output
+ );
+ }
+
+ public function testQueryForInterwikiAnnotation() {
+
+ $this->stringBuilder
+ ->addString( '[[Has type::Page]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Use for interwiki annotation', SMW_NS_PROPERTY ) )
+ ->doEdit( $this->stringBuilder->getString() );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( __METHOD__ . '-1' ) )
+ ->doEdit( '[[Use for interwiki annotation::Interwiki link]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( __METHOD__ . '-2' ) )
+ ->doEdit( '[[Use for interwiki annotation::iw-test:Interwiki link]]' );
+
+ $this->stringBuilder
+ ->addString( '[[Use for interwiki annotation::iw-test:Interwiki link]]' );
+
+ $description = $this->queryParser->getQueryDescription( $this->stringBuilder->getString() );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+ $query->setLimit( 10 );
+
+ // Expects only one result with an interwiki being used as differentiator
+ $this->subjects[] = DIWikiPage::newFromTitle(Title::newFromText( __METHOD__ . '-2' ) );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $this->subjects,
+ $this->getStore()->getQueryResult( $query )
+ );
+
+ $this->subjects[] = DIWikiPage::newFromTitle(Title::newFromText( __METHOD__ . '-1' ) );
+ }
+
+ private function fetchSerializedRdfOutputFor( array $pages ) {
+
+ $this->subjects = $pages;
+
+ $instance = new ExportController( new RDFXMLSerializer() );
+
+ ob_start();
+ $instance->printPages( $pages );
+ return ob_get_clean();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ApiTestCaseProcessor.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ApiTestCaseProcessor.php
new file mode 100644
index 00000000..6ecc4c7c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ApiTestCaseProcessor.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use SMW\Tests\Utils\File\ContentsReader;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ApiTestCaseProcessor extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var MwApiFactory
+ */
+ private $mwApiFactory;
+
+ /**
+ * @var StringValidator
+ */
+ private $stringValidator;
+
+ /**
+ * @var boolean
+ */
+ private $debug = false;
+
+ /**
+ * @param MwApiFactory mwApiFactory
+ * @param StringValidator
+ */
+ public function __construct( $mwApiFactory, $stringValidator ) {
+ $this->mwApiFactory = $mwApiFactory;
+ $this->stringValidator = $stringValidator;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public function setDebugMode( $debugMode ) {
+ $this->debug = $debugMode;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $testCaseLocation
+ */
+ public function setTestCaseLocation( $testCaseLocation ) {
+ $this->testCaseLocation = $testCaseLocation;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param array $case
+ */
+ public function process( array $case ) {
+
+ if ( !isset( $case['api'] ) ) {
+ return;
+ }
+
+ $parameters = [];
+
+ if ( isset( $case['api']['parameters'] ) ) {
+ $parameters = $case['api']['parameters'];
+ }
+
+ $res = $this->mwApiFactory->doApiRequest(
+ $parameters
+ );
+
+ $this->assertOutputForCase( $case, json_encode( $res ) );
+ }
+
+ private function assertOutputForCase( $case, $text ) {
+
+ // Avoid issue with \r carriage return and \n new line
+ $text = str_replace( "\r\n", "\n", $text );
+
+ if ( isset( $case['assert-output']['to-contain'] ) ) {
+
+ if ( isset( $case['assert-output']['to-contain']['contents-file'] ) ) {
+ $contents = ContentsReader::readContentsFrom(
+ $this->testCaseLocation . $case['assert-output']['to-contain']['contents-file']
+ );
+ } else {
+ $contents = $case['assert-output']['to-contain'];
+ }
+
+ $this->stringValidator->assertThatStringContains(
+ $contents,
+ $text,
+ $case['about']
+ );
+ }
+
+ if ( isset( $case['assert-output']['not-contain'] ) ) {
+
+ if ( isset( $case['assert-output']['not-contain']['contents-file'] ) ) {
+ $contents = ContentsReader::readContentsFrom(
+ $this->testCaseLocation . $case['assert-output']['not-contain']['contents-file']
+ );
+ } else {
+ $contents = $case['assert-output']['not-contain'];
+ }
+
+ $this->stringValidator->assertThatStringNotContains(
+ $contents,
+ $text,
+ $case['about']
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/P106.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/P106.txt
new file mode 100644
index 00000000..cdb33450
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/P106.txt
@@ -0,0 +1,24 @@
+* Has type: [[Has type::Text]]
+
+== Preferred property labels ==
+* [[Has preferred property label::occupation@en]]
+* [[Has preferred property label::Tätigkeit@de]]
+* [[Has preferred property label::occupation@fr]]
+* [[Has preferred property label::ocupación@es]]
+* [[Has preferred property label::род занÑтий@ru]]
+* [[Has preferred property label::occupazione@it]]
+* [[Has preferred property label::èŒä¸š@zh-hans]]
+* [[Has preferred property label::è·æ¥­@ja]]
+
+<!-- Causes error as it is already defined above -->
+* [[Has preferred property label::è·ç¨®@ja]]
+
+== Property descriptions ==
+* [[Has property description::occupation of a person; see also field of work (Property:P101)@en]]
+* [[Has property description::Beruf oder andere Tätigkeit einer Person (ergänzt durch Arbeitsgebiet: Property:P101)@de]]
+* [[Has property description::actividad laboral u otra ocupación de la persona; véase también campo de trabajo (propiedad 101)@es]]
+* [[Has property description::qualité d'une personne (métier, hobby...), voir aussi domaine d'activité (Property:P101) et fonction (Property:P39)@fr]]
+* [[Has property description::attività lavorativa svolta, vedi anche campo di lavoro (Property: P101)@it]]
+* [[Has property description::профеÑÑÐ¸Ñ Ð¿ÐµÑ€Ñоны; Ñм. также ÑвойÑтво облаÑÑ‚ÑŒ деÑтельноÑти (Property:P101)@ru]]
+* [[Has property description::èŒä¸šå³èŒåœºä¸Šçš„专门行业,是对劳动的分类。@zh-hans]]
+* [[Has property description::人物ã®è·æ¥­ã€‚「専門分野ã€(Property:P101) ã‚‚å‚ç…§@ja]] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.0.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.0.txt
new file mode 100644
index 00000000..49e8202d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.0.txt
@@ -0,0 +1 @@
+{"query":{"API_test_property":{"label":"API test property","key":"API_test_property","description":{"en":""},"prefLabel":{"en":""}}},"query-continue-offset":0,"version":1,"meta":{"type":"property","limit":10,"count":1,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.1.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.1.txt
new file mode 100644
index 00000000..d227be4f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.1.txt
@@ -0,0 +1 @@
+{"query":{"API_test_concept":{"label":"API test concept","key":"API_test_concept"}},"query-continue-offset":0,"version":1,"meta":{"type":"concept","limit":10,"count":1,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.2.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.2.txt
new file mode 100644
index 00000000..ab4548f5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.2.txt
@@ -0,0 +1 @@
+{"query":{"API_test_category":{"label":"API test category","key":"API_test_category"}},"query-continue-offset":0,"version":1,"meta":{"type":"category","limit":10,"count":1,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.3.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.3.txt
new file mode 100644
index 00000000..e5a1154b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.3.txt
@@ -0,0 +1 @@
+{"query":{"API_test_category#14":{"label":"API test category","key":"API_test_category","ns":"14"},"API_test_concept#108":{"label":"API test concept","key":"API_test_concept","ns":"108"},"API_test_property#102":{"label":"API test property","key":"API_test_property","ns":"102"}},"query-continue-offset":0,"version":1,"meta":{"type":"article","limit":10,"count":3,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.4.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.4.txt
new file mode 100644
index 00000000..ce7d3398
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.4.txt
@@ -0,0 +1 @@
+{"query":["text 1","text 2"],"query-continue-offset":0,"version":1,"meta":{"type":"pvalue","limit":10,"count":2,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.5.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.5.txt
new file mode 100644
index 00000000..7e2c00bb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.5.txt
@@ -0,0 +1 @@
+{"query":["Page 1","Page 2"],"query-continue-offset":0,"version":1,"meta":{"type":"pvalue","limit":10,"count":2,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.6.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.6.txt
new file mode 100644
index 00000000..9e704817
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/a-0001.6.txt
@@ -0,0 +1 @@
+{"query":["1 January 1970","2 January 1971"],"query-continue-offset":0,"version":1,"meta":{"type":"pvalue","limit":10,"count":2,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/file-upload.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/file-upload.txt
new file mode 100644
index 00000000..e3d33a13
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/file-upload.txt
@@ -0,0 +1 @@
+Test file for a non image upload! \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-480.png b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-480.png
new file mode 100644
index 00000000..4353df8e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-480.png
Binary files differ
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-88.png b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-88.png
new file mode 100644
index 00000000..937d6493
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/image-upload-88.png
Binary files differ
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/numeric-sorting.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/numeric-sorting.txt
new file mode 100644
index 00000000..ec97f2cf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/numeric-sorting.txt
@@ -0,0 +1,20 @@
+https://phabricator.wikimedia.org/T8948
+{{#subobject:
+ |Has page=Antonov An-2
+ |@category=Numeric sorting example
+}}{{#subobject:
+ |Has page=Antonov An-218
+ |@category=Numeric sorting example
+}}{{#subobject:
+ |Has page=Antonov An-22
+ |@category=Numeric sorting example
+}}{{#subobject:
+ |Has page=Antonov An-225
+ |@category=Numeric sorting example
+}}{{#subobject:
+ |Has page=Antonov An-24
+ |@category=Numeric sorting example
+}}{{#subobject:
+ |Has page=Antonov An-3
+ |@category=Numeric sorting example
+}}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.1.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.1.txt
new file mode 100644
index 00000000..f1fc0607
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.1.txt
@@ -0,0 +1,20 @@
+@source: http://www.simile-widgets.org/exhibit3/examples/other-versions/HEAD/icd/icd10-infectious.json
+
+{{#subobject:
+ |@category=P0211
+ |@json={
+ "kind": "chapter",
+ "code": "I",
+ "exclusion": "carrier or suspected carrier of infectious diseaseZ22.-",
+ "icdId": "http://id.who.int/icd/icd10/I",
+ "inclusion": "diseases generally recognized as communicable or transmissible",
+ "label": "Certain infectious and parasitic diseases",
+ "link": "http://apps.who.int/classifications/icd10/browse/2010/en#/I",
+ "subclasses": [
+ "http://id.who.int/icd/icd10/A00-A09",
+ "http://id.who.int/icd/icd10/A15-A19",
+ "http://id.who.int/icd/icd10/A20-A28"
+ ],
+ "id": "http://id.who.int/icd/icd10/I"
+}
+}} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.2.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.2.txt
new file mode 100644
index 00000000..4bb0aad5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.2.txt
@@ -0,0 +1,27 @@
+@source: http://www.simile-widgets.org/exhibit3/examples/other-versions/HEAD/icd/icd10-infectious.json
+
+{{#set:
+ |@json={
+ "kind": "block",
+ "code": "A00-A09",
+ "icdId": "http://id.who.int/icd/icd10/A00-A09",
+ "label": "Intestinal infectious diseases",
+ "link": "http://apps.who.int/classifications/icd10/browse/2010/en#/A00-A09",
+ "superclasses": [
+ "http://id.who.int/icd/icd10/I"
+ ],
+ "subclasses": [
+ "http://id.who.int/icd/icd10/A00",
+ "http://id.who.int/icd/icd10/A01",
+ "http://id.who.int/icd/icd10/A02",
+ "http://id.who.int/icd/icd10/A03",
+ "http://id.who.int/icd/icd10/A04",
+ "http://id.who.int/icd/icd10/A05",
+ "http://id.who.int/icd/icd10/A06",
+ "http://id.who.int/icd/icd10/A07",
+ "http://id.who.int/icd/icd10/A08",
+ "http://id.who.int/icd/icd10/A09"
+ ],
+ "id": "http://id.who.int/icd/icd10/A00-A09"
+}
+}} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.3.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.3.txt
new file mode 100644
index 00000000..b728ce6b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0211.3.txt
@@ -0,0 +1,11 @@
+3+ depth is not permitted
+
+{{#set:
+ |@json={
+ "foo": {
+ "kind": {
+ "kind": "bar"
+ }
+ }
+}
+}} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0303.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0303.txt
new file mode 100644
index 00000000..267b4374
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0303.txt
@@ -0,0 +1,7 @@
+{{#set: Has effect=Foo,
+Bar |+sep=,
+}}
+
+{{#subobject: Has effect=Foo,
+Bar |+sep=,
+}}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.de.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.de.txt
new file mode 100644
index 00000000..5625a2e4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.de.txt
@@ -0,0 +1,11 @@
+@source http://www.gutenberg.org/files/34811/34811-h/34811-h.htm
+
+Title: Buddenbrooks - Verfall einer Familie
+
+Author: Thomas Mann
+
+Release Date: January 1, 2011 [EBook #34811]
+
+Language: German
+
+[[Has text::Und die kleine Antonie, achtjährig und zartgebaut, in einem Kleidchen aus ganz leichter changierender Seide, den hübschen Blondkopf ein wenig vom Gesichte des Großvaters abgewandt, blickte aus ihren graublauen Augen angestrengt nachdenkend und ohne etwas zu sehen ins Zimmer hinein, wiederholte noch einmal: »Was ist das«, sprach darauf langsam: »Ich glaube, daß mich Gott«, fügte, während ihr Gesicht sich aufklärte, rasch hinzu: »– geschaffen hat samt allen Kreaturen« ...]] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.fr.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.fr.txt
new file mode 100644
index 00000000..96877361
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0439.fr.txt
@@ -0,0 +1,13 @@
+@source http://www.gutenberg.org/cache/epub/22768/pg22768-images.html
+
+Title: L'enfer (1 of 2) La Divine Comédie - Traduit par Rivarol
+
+Author: Dante Alighieri
+
+Translator: Antoine Rivarol (de)
+
+Release Date: September 26, 2007 [EBook #22768]
+
+Language: French
+
+[[Has text::Dès les premières heures de notre publication, nous avons annoncé le chef-d'oeuvre du poëte florentin comme devant figurer en première ligne parmi les joyaux de notre modeste écrin. Nous avons voulu, au début, donner accès à tous les ouvrages consacrés par le temps et par l'admiration universelle. Un succès constant pendant quatre longues et parfois difficiles années, nous a prouvé que nous nous étions très rarement trompé sur ...]] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0444.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0444.txt
new file mode 100644
index 00000000..bce2c2dc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0444.txt
@@ -0,0 +1 @@
+[[Has text::[[Lorem ipsum]] dolor sit amet, [[Has page::consectetur adipiscing elit]]. In [http://example.org/eleifend eleifend] cursus dignissim. Suspendisse potenti. [[Has page::Curabitur aliquet|Bar]] malesuada ex sed efficitur. [[Nullam id ante|Foo]] eget lacus rutrum tincidunt eu et lacus. Aliquam sed consequat orci. Nulla sodales neque magna, nec sollicitudin erat aliquam ut. Sed sed vulputate tortor, in [[vestibulum nibh]] [[Has number::42]] [[Has date::01-01-2020]]]].
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0459-keyword-formatter-schema.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0459-keyword-formatter-schema.json
new file mode 100644
index 00000000..a4dda206
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0459-keyword-formatter-schema.json
@@ -0,0 +1,15 @@
+{
+ "description": "Specifies a formatting schema for a keyword type",
+ "type": "LINK_FORMAT_SCHEMA",
+ "rule": {
+ "link_to": "SPECIAL_ASK",
+ "parameters": {
+ "format": "list"
+ }
+ },
+ "tags": [
+ "formatter",
+ "link formatter",
+ "keyword"
+ ]
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-error.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-error.txt
new file mode 100644
index 00000000..148edfc8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-error.txt
@@ -0,0 +1,2 @@
+* Foo
+* Bar
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-other-license.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-other-license.json
new file mode 100644
index 00000000..cffd0c7d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502-other-license.json
@@ -0,0 +1,4 @@
+{
+ "CC Zero": "Public Domain Dedication",
+ "PD": "Public Domain"
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502.txt
new file mode 100644
index 00000000..fc84f4af
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/p-0502.txt
@@ -0,0 +1,49 @@
+[https://www.cs.umd.edu/projects/plus/SHOE/onts/docmnt1.0.html Models documents of all kinds, but focuses on publications]
+
+* Communication|Communication
+** Document
+*** Abstract
+*** Comment
+*** Correspondence
+**** Discussion
+**** Email
+**** Letter
+**** Postcard
+*** Form
+*** Guideline
+*** Homepage
+**** OrganizationHomepage
+**** PersonalHomepage
+*** Index
+*** Lecture
+*** Manuscript
+*** Minutes
+*** Preprint
+*** Promotion
+*** Publication
+**** Advertisement
+**** Article
+***** BookArticle
+***** ConferencePaper
+***** JournalArticle
+***** WorkshopPaper
+**** Book
+**** Dictionary
+**** Editorial
+**** Manual
+**** Periodical
+***** Journal
+***** Magazine
+***** Newsletter
+***** Newspaper
+**** Proceedings
+**** Regulation
+**** Specification
+**** TechnicalReport
+**** Thesis
+***** DoctoralThesis
+***** MastersThesis
+**** Review
+** PhoneCall
+** Software
+** Speech
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.friends.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.friends.txt
new file mode 100644
index 00000000..3d712e8d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.friends.txt
@@ -0,0 +1,109 @@
+<pre>
+Andy Mars,USA,business
+Andy Mars,Prague,both
+Andy Mars,Japan,pleasure
+John Maier,Prague,both
+John Maier,USA,both
+John Maier,Greece,pleasure
+Yan Chow,Canada,pleasure
+Yan Chow,USA,business
+Yan Chow,China,business
+Mike Bloom,Amsterdam,both
+Mike Bloom,USA,both
+Charles Banning,USA,pleasure
+Charles Banning,Greece,pleasure
+Charles Banning,Andora,pleasure
+Kevin Mikaelson,USA,both
+Kevin Mikaelson,Japan,business
+Kevin Mikaelson,Andora,pleasure
+Charlotte Beans,Prague,pleasure
+Charlotte Beans,USA,both
+Charlotte Beans,Kazakhstan,pleasure
+Yumi Tanaka,USA,both
+Yumi Tanaka,Greece,pleasure
+Yumi Tanaka,Amsterdam,pleasure
+Rosalia Alvarez,USA,pleasure
+Rosalia Alvarez,Canada,pleasure
+Rosalia Alvarez,China,pleasure
+Mandy Rose,Amsterdam,pleasure
+Mandy Rose,Russia,pleasure
+James Ross,Amsterdam,business
+Evelyne Lynn,Germany,business
+Evelyne Lynn,Greece,pleasure
+Evelyne Lynn,Italy,pleasure
+Michael Chester,Amsterdam,pleasure
+Michael Chester,Germany,pleasure
+Michael Chester,Thailand,pleasure
+</pre>
+
+{{#subobject:
+ |Person=Andy Mars |Place visited=USA |Type of visit=business
+}}{{#subobject:
+ |Person=Andy Mars |Place visited=Prague |Type of visit=both
+}}{{#subobject:
+ |Person=Andy Mars |Place visited=Japan |Type of visit=pleasure
+}}{{#subobject:
+ |Person=John Maier |Place visited=Prague |Type of visit=both
+}}{{#subobject:
+ |Person=John Maier |Place visited=USA |Type of visit=both
+}}{{#subobject:
+ |Person=John Maier |Place visited=Greece |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Yan Chow |Place visited=Canada |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Yan Chow |Place visited=,USA |Type of visit=business
+}}{{#subobject:
+ |Person=Yan Chow |Place visited=China |Type of visit=business
+}}{{#subobject:
+ |Person=Mike Bloom |Place visited=Amsterdam |Type of visit=both
+}}{{#subobject:
+ |Person=Mike Bloom |Place visited=USA |Type of visit=both
+}}{{#subobject:
+ |Person=Charles Banning |Place visited=USA |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Charles Banning |Place visited=,Greece |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Charles Banning |Place visited=Andora |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Kevin Mikaelson |Place visited=USA |Type of visit=both
+}}{{#subobject:
+ |Person=Kevin Mikaelson |Place visited=Japan |Type of visit=business
+}}{{#subobject:
+ |Person=Kevin Mikaelson |Place visited=Andora |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Charlotte Beans |Place visited=Prague |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Charlotte Beans |Place visited=USA |Type of visit=both
+}}{{#subobject:
+ |Person=Charlotte Beans |Place visited=Kazakhstan |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Yumi Tanaka |Place visited=USA |Type of visit=both
+}}{{#subobject:
+ |Person=Yumi Tanaka |Place visited=Greece |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Yumi Tanaka |Place visited=Amsterdam |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Rosalia Alvarez |Place visited=USA |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Rosalia Alvarez |Place visited=Canada |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Rosalia Alvarez |Place visited=China |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Mandy Rose |Place visited=Amsterdam |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Mandy Rose |Place visited=Russia |Type of visit=pleasure
+}}{{#subobject:
+ |Person=James Ross |Place visited=Amsterdam |Type of visit=business
+}}{{#subobject:
+ |Person=Evelyne Lynn |Place visited=Germany |Type of visit=business
+}}{{#subobject:
+ |Person=Evelyne Lynn |Place visited=Greece |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Evelyne Lynn |Place visited=Italy |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Michael Chester |Place visited=Amsterdam |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Michael Chester |Place visited=Germany |Type of visit=pleasure
+}}{{#subobject:
+ |Person=Michael Chester |Place visited=Thailand |Type of visit=pleasure
+}} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.persons.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.persons.txt
new file mode 100644
index 00000000..07186c17
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.persons.txt
@@ -0,0 +1,46 @@
+<pre>
+Andy Mars,32,male,married
+John Maier,32,male,married
+Peter Dunn,32,male,married
+Yan Chow,32,male,married
+Mike Bloom,31,male,married
+Charles Banning,33,male,single
+Kevin Mikaelson,32,male,single
+Charlotte Beans,30,female,married
+Yumi Tanaka,31,female,married
+Rosalia Alvarez,31,female,married
+Mandy Rose,31,female,married
+James Ross,26,male,single
+Evelyne Lynn,31,female,married
+Michael Chester,34,male,single
+</pre>
+
+{{#subobject:
+ |Person=Andy Mars |Age=32 |Gender= male |Material status= married
+}}{{#subobject:
+ |Person=John Maier |Age=32 |Gender=male |Material status=married
+}}{{#subobject:
+ |Person=Peter Dunn |Age=32 |Gender=male |Material status=married
+}}{{#subobject:
+ |Person=Yan Chow |Age=32 |Gender=male |Material status=married
+}}{{#subobject:
+ |Person=Mike Bloom |Age=31 |Gender=male |Material status=married
+}}{{#subobject:
+ |Person=Charles Banning |Age=33 |Gender=male |Material status=single
+}}{{#subobject:
+ |Person=Kevin Mikaelson |Age=32 |Gender=male |Material status=single
+}}{{#subobject:
+ |Person=Charlotte Beans |Age=30 |Gender=female |Material status=married
+}}{{#subobject:
+ |Person=Yumi Tanaka |Age=31 |Gender=female |Material status=married
+}}{{#subobject:
+ |Person=Rosalia Alvarez |Age=31 |Gender=female |Material status=married
+}}{{#subobject:
+ |Person=Mandy Rose |Age=31 |Gender=female |Material status=married
+}}{{#subobject:
+ |Person=James Ross |Age=26 |Gender=male |Material status=single
+}}{{#subobject:
+ |Person=Evelyne Lynn |Age=31 |Gender=female |Material status=married
+}}{{#subobject:
+ |Person=Michael Chester |Age=34 |Gender=male |Material status=single
+}} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.visits.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.visits.txt
new file mode 100644
index 00000000..d227ce3c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0618.visits.txt
@@ -0,0 +1,27 @@
+<pre>
+Andy Mars,John Maier
+Andy Mars,Peter Dunn
+Andy Mars,Yan Chow
+Andy Mars,Mike Bloom
+Andy Mars,Charles Banning
+Andy Mars,Kevin Mikaelson
+John Maier,Charlotte Beans
+John Maier,James Ross
+John Maier,Evelyne Lynn
+Peter Dunn,Yumi Tanaka
+Peter Dunn,Michael Chester
+Yan Chow,Rosalia Alvarez
+Mike Bloom,Mandy Rose
+</pre>
+
+{{#subobject:Andy Mars
+ |Person=Andy Mars|Has friend=John Maier,Peter Dunn,Yan Chow,Mike Bloom,Charles Banning,Kevin Mikaelson |+sep=, |@category=Friends
+}}{{#subobject:John Maier
+ |Person=John Maier |Has friend=Charlotte Beans, James Ross,Evelyne Lynn |+sep=, |@category=Friends
+}}{{#subobject:Peter Dunn
+ |Person=Peter Dunn |Has friend=Yumi Tanaka,Michael Chester |+sep=, |@category=Friends
+}}{{#subobject:Yan Chow
+ |Person=Yan Chow |Has friend=Rosalia Alvarez|+sep=, |@category=Friends
+}}{{#subobject:Mike Bloom
+ |Person=Mike Bloom |Has friend=Mandy Rose|+sep=, |@category=Friends
+}} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-1.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-1.txt
new file mode 100644
index 00000000..0c68a6c2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-1.txt
@@ -0,0 +1,3 @@
+[[Has text::Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vulputate tortor nec magna volutpat suscipit. Aliquam erat volutpat. Nulla aliquam, lectus ut dictum sollicitudin, justo magna dapibus turpis, eget tincidunt justo tellus id libero. Aliquam tortor leo, aliquam eu feugiat in, efficitur ac nisl. Ut elit ante, rutrum ac varius vel, faucibus in magna. Mauris euismod erat sit amet vulputate placerat. Maecenas vitae urna eleifend, scelerisque metus vitae, rhoncus metus. Vestibulum luctus, tellus et blandit laoreet, mauris odio commodo mauris, at porttitor libero orci sit amet quam. Fusce at laoreet tortor.]]
+
+[[Category:Q0907]] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-2.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-2.txt
new file mode 100644
index 00000000..64a968f9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/q-0907-2.txt
@@ -0,0 +1,3 @@
+[[Has url::http://example.com/chart?chs=500x500&chma=0,0,100,100&cht=p&chco=FF0000%2CFFFF00%7CFF8000%2C00FF00%7C00FF00%2C0000FF&chd=t%3A122%2C42%2C17%2C10%2C8%2C7%2C7%2C7%2C7%2C6%2C6%2C6%2C6%2C5%2C5&chl=122%7C42%7C17%7C10%7C8%7C7%7C7%7C7%7C7%7C6%7C6%7C6%7C6%7C5%7C5&chdl=android%7Cjava%7Cstack-trace%7Cbroadcastreceiver%7Candroid-ndk%7Cuser-agent%7Candroid-webview%7Cwebview%7Cbackground%7Cmultithreading%7Candroid-source%7Csms%7Cadb%7Csollections%7Cactivity]]
+
+[[Category:Q0907]] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.10.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.10.txt
new file mode 100644
index 00000000..9a34c336
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.10.txt
@@ -0,0 +1 @@
+{"query":["A0001\/3","A0001\/4"],"query-continue-offset":0,"version":1,"meta":{"type":"psubject","limit":10,"count":2,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.11.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.11.txt
new file mode 100644
index 00000000..05ef228f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.11.txt
@@ -0,0 +1 @@
+{"query":["A0001\/4"],"query-continue-offset":0,"version":1,"meta":{"type":"psubject","limit":10,"count":1,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.7.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.7.txt
new file mode 100644
index 00000000..dcb97b80
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.7.txt
@@ -0,0 +1 @@
+{"query":{"subject":"A0001\/1#0##","data":[{"property":"API_text_property","dataitem":[{"type":2,"item":"text 1"}]},{"property":"_MDAT","dataitem":[{"type":6,"item":".*"}]},{"property":"_SKEY","dataitem":[{"type":2,"item":"A0001\/1"}]}],"serializer":"SMW\\Serializers\\SemanticDataSerializer","version":2},"meta":{"type":"subject"}.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.8.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.8.txt
new file mode 100644
index 00000000..b8a8827b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.8.txt
@@ -0,0 +1 @@
+{"query":"<div class=\"smwb-datasheet smwb-theme-light\"><div class=\"smw-table smwb-factbox\"><div class=\"smw-table-row smwb-title\"><a href=\".*\/A0001\/1\" title=\"A0001\/1\">A0001\/1<\/a><\/div><\/div><div class=\"smw-table smwb-factbox\"><div class=\"smw-table-row smwb-actions\"><a href=\".*?title=.*&amp;offset=0&amp;dir=both&amp;article=A0001%2F1#smw_browse_incoming\" class=\"smw_browse_show_incoming\">Show incoming properties<\/a>&#160;\n<\/div><\/div><div class=\"smw-table smwb-factbox smwb-bottom\"><div class=\"smw-table-row smwb-propvalue\"><div class=\"smw-table-cell smwb-cell smwb-prophead\"><a href=\".*\/Property:API_text_property\" title=\"Property:API text property\">API\u00a0text\u00a0property<\/a>\n<\/div><div class=\"smw-table-cell smwb-cell smwb-propval\"><span class=\"smwb-value\">text 1&#160;&#160;<span class=\"smwsearch\"><a href=\".*\/.*\/:API-20text-20property\/text-201\" title=\".*\/:API-20text-20property\/text-201\">+<\/a><\/span><\/span><\/div><\/div><div class=\"smw-table-row smwb-propvalue\"><div class=\"smw-table-cell smwb-cell smwb-prophead\"><span class=\"smw-highlighter\" data-type=\"1\" data-state=\"inline\" data-title=\"Property\" title=\"&quot;Modification date&quot; is a predefined property that corresponds to the date of the last modification of a subject and is provided by Semantic MediaWiki.\"><span class=\"smwbuiltin\"><a href=\".*\/Property:Modification_date\" title=\"Property:Modification date\">Modification\u00a0date<\/a><\/span><span class=\"smwttcontent\">\"Modification date\" is a predefined property that corresponds to the date of the last modification of a subject and is provided by <a rel=\"nofollow\" class=\"external text\" href=\"https:\/\/www.semantic-mediawiki.org\/wiki\/Help:Special_properties\">Semantic MediaWiki<\/a>.<\/span><\/span>\n<\/div><div class=\"smw-table-cell smwb-cell smwb-propval\"><span class=\"smwb-value\">.*<span class=\"smwsearch\"><a href=\".*\/.*\/:Modification-20date\/.*\" title=\".*\/:Modification-20date\/.*\">+<\/a><\/span><\/span><\/div><\/div><\/div><div class=\"smw-table smwb-factbox\"><div class=\"smw-table-row smwb-center\">&#160;\n<\/div><\/div><\/div><div class=\"smwb-form\"><div style=\"margin-top:15px;\"><\/div><form name=\"smwbrowse\" action=\".*\" method=\"get\"><input type=\"hidden\" name=\"title\" value=\".*\"\/><div class=\"smwb-input\"><div class=\"input-field\"><input dir=\"ltr\" name=\"article\" size=\"40\" id=\"smw-page-input\" class=\"input smw-page-input autocomplete-arrow mw-ui-input\" value=\"A0001\/1\"\/><\/div><div class=\"button-field\"><input type=\"submit\" class=\"input-button mw-ui-button\" value=\"Go\"\/><\/div><\/div><\/form><\/div><div class=\"smwb-modules\" data-modules=\"[]\"><\/div>","meta":{"type":"subject"}.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.9.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.9.txt
new file mode 100644
index 00000000..9f533ef8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0001.9.txt
@@ -0,0 +1 @@
+{"query":["A0001\/3"],"query-continue-offset":0,"version":1,"meta":{"type":"psubject","limit":10,"count":1,"isFromCache":false,"queryTime":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.0.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.0.json
new file mode 100644
index 00000000..d4b80586
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.0.json
@@ -0,0 +1 @@
+{"query":{"printrequests":[{"label":"","key":"","redi":"","typeid":"_wpg","mode":2,"format":false},{"label":"API test page","key":"API_test_page","redi":"","typeid":"_wpg","mode":1,"format":""}],"results":{"Example\/A0002\/1":{"printouts":{"API test page":[{"fulltext":"123","fullurl":".*\/123","namespace":0,"exists":"","displaytitle":""}]},"fulltext":"Example\/A0002\/1","fullurl":".*\/Example\/A0002\/1","namespace":0,"exists":"1","displaytitle":""}},"serializer":"SMW\\Serializers\\QueryResultSerializer","version":2,"meta":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.1.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.1.json
new file mode 100644
index 00000000..ceb7b29e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.1.json
@@ -0,0 +1 @@
+{"query":{"printrequests":[{"label":"","key":"","redi":"","typeid":"_wpg","mode":2,"format":false},{"label":"API test page","key":"API_test_page","redi":"","typeid":"_wpg","mode":1,"format":""}],"results":[{"Example\/A0002\/1":{"printouts":{"API test page":[{"fulltext":"123","fullurl":".*\/123","namespace":0,"exists":"","displaytitle":""}]},"fulltext":"Example\/A0002\/1","fullurl":".*\/Example\/A0002\/1","namespace":0,"exists":"1","displaytitle":""}}],"serializer":"SMW\\Serializers\\QueryResultSerializer","version":3,"meta":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.2.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.2.json
new file mode 100644
index 00000000..55c488a2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.2.json
@@ -0,0 +1 @@
+{"query":{"printrequests":[{"label":"","key":"","redi":"","typeid":"_wpg","mode":2,"format":false},{"label":"API test page","key":"API_test_page","redi":"","typeid":"_wpg","mode":1,"format":false}],"results":{"Example\/A0002\/1":{"printouts":{"API test page":[{"fulltext":"123","fullurl":".*\/123","namespace":0,"exists":"","displaytitle":""}]},"fulltext":"Example\/A0002\/1","fullurl":".*\/Example\/A0002\/1","namespace":0,"exists":"1","displaytitle":""}},"serializer":"SMW\\Serializers\\QueryResultSerializer","version":2,"meta":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.3.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.3.json
new file mode 100644
index 00000000..32b19aa7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.a-0002.3.json
@@ -0,0 +1 @@
+{"query":{"printrequests":[{"label":"","key":"","redi":"","typeid":"_wpg","mode":2,"format":false},{"label":"API test page","key":"API_test_page","redi":"","typeid":"_wpg","mode":1,"format":false}],"results":[{"Example\/A0002\/1":{"printouts":{"API test page":[{"fulltext":"123","fullurl":".*\/123","namespace":0,"exists":"","displaytitle":""}]},"fulltext":"Example\/A0002\/1","fullurl":".*\/Example\/A0002\/1","namespace":0,"exists":"1","displaytitle":""}}],"serializer":"SMW\\Serializers\\QueryResultSerializer","version":3,"meta":.*} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.0.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.0.csv
new file mode 100644
index 00000000..2dcf6f91
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.0.csv
@@ -0,0 +1,5 @@
+,"Has text","Has number"
+Example/S0022/1,"Some example",
+Example/S0022/2,,"123,345"
+Example/S0022/3,ABC,123
+Example/S0022/4,DEF,123 \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.1.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.1.csv
new file mode 100644
index 00000000..3401095c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.1.csv
@@ -0,0 +1,4 @@
+Example/S0022/1,"Some example",
+Example/S0022/2,,"123,345"
+Example/S0022/3,ABC,123
+Example/S0022/4,DEF,123 \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.2.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.2.csv
new file mode 100644
index 00000000..c0953f0a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.2.csv
@@ -0,0 +1,5 @@
+"Has number","Has text"
+,"Some example"
+"123,345",
+123,ABC
+123,DEF
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.3.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.3.csv
new file mode 100644
index 00000000..5fba776e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.3.csv
@@ -0,0 +1,4 @@
+"Has number","Has text"
+,"Some example"
+"123,345",
+123,"ABC,DEF"
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.4.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.4.csv
new file mode 100644
index 00000000..b19ab4c3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.4.csv
@@ -0,0 +1,4 @@
+Example/S0022/1,"Some example",
+Example/S0022/2,,123;345
+Example/S0022/3,ABC,123
+Example/S0022/4,DEF,123 \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.5.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.5.csv
new file mode 100644
index 00000000..ee778599
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.5.csv
@@ -0,0 +1,5 @@
+|"Has number"|"Has text"
+Example/S0022/1||"Some example"
+Example/S0022/2|123+345|
+Example/S0022/3|123|ABC
+Example/S0022/4|123|DEF
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.6.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.6.csv
new file mode 100644
index 00000000..6fd9cf66
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.6.csv
@@ -0,0 +1,4 @@
+"Has number","Has text"
+,"Some example"
+123;345,
+123,ABC;DEF
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.7.csv b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.7.csv
new file mode 100644
index 00000000..cc890ed1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0022.7.csv
@@ -0,0 +1,4 @@
+"Has number"|"Has text"
+|"Some example"
+123;345|
+123|ABC;DEF
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.0.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.0.txt
new file mode 100644
index 00000000..c2c7304e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.0.txt
@@ -0,0 +1,12 @@
+#FORMAT: BEACON
+#PREFIX: http://d-nb.info/gnd/
+#TARGET:.*
+#VERSION: 0.1
+#HOMEPAGE: https://www.semantic-mediawiki.org/w/index.php?title=Help:BEACON
+#FEED: https://www.semantic-mediawiki.org/w/index.php?title=BEACON&action=render
+#LINK: http://www.w3.org/2000/01/rdf-schema#seeAlso
+#INSTITUTION: Semantic MediaWiki
+#MESSAGE: Person test data in Semantic MediaWiki
+#TIMESTAMP: .*
+#UPDATE: always
+123456789||John Doe \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.1.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.1.txt
new file mode 100644
index 00000000..8ff483d5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/res.s-0025.1.txt
@@ -0,0 +1,13 @@
+#FORMAT: BEACON
+#PREFIX: http://d-nb.info/gnd/
+#TARGET:.*
+#VERSION: 0.1
+#HOMEPAGE: https://www.semantic-mediawiki.org/w/index.php?title=Help:BEACON
+#FEED: https://www.semantic-mediawiki.org/w/index.php?title=BEACON&action=render
+#LINK: http://www.w3.org/2000/01/rdf-schema#seeAlso
+#INSTITUTION: Semantic MediaWiki
+#MESSAGE: Person test data in Semantic MediaWiki
+#TIMESTAMP: .*
+#UPDATE: always
+123456789||John Doe
+987654321||Jane Doe \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.0.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.0.txt
new file mode 100644
index 00000000..f5f01811
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.0.txt
@@ -0,0 +1 @@
+{"printrequests":[{"label":"","key":"","redi":"","typeid":"_wpg","mode":2,"format":false},{"label":"Has text","key":"Has_text","redi":"","typeid":"_txt","mode":1,"format":""},{"label":"Has number","key":"Has_number","redi":"","typeid":"_num","mode":1,"format":""}],"results":{"Example/S0020/1":{"printouts":{"Has text":["Some example"],"Has number":[]},"fulltext":"Example/S0020/1","fullurl":".*Example/S0020/1","namespace":0,"exists":"1","displaytitle":""},"Example/S0020/2":{"printouts":{"Has text":[],"Has number":[123,345]},"fulltext":"Example/S0020/2","fullurl":".*Example/S0020/2","namespace":0,"exists":"1","displaytitle":""}},"serializer":"SMW\\Serializers\\QueryResultSerializer","version":2,"rows":2} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.1.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.1.txt
new file mode 100644
index 00000000..106f3d94
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.1.txt
@@ -0,0 +1 @@
+{"Example/S0020/1#0##":{"Has text":["Some example"],"Has number":[]},"Example/S0020/2#0##":{"Has text":[],"Has number":["123","345"]}} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.2.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.2.txt
new file mode 100644
index 00000000..fae10c19
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0020.2.txt
@@ -0,0 +1 @@
+[{"Has text":["Some example"],"Has number":[]},{"Has text":[],"Has number":["123","345"]}] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon-intro.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon-intro.txt
new file mode 100644
index 00000000..82db62e2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon-intro.txt
@@ -0,0 +1,11 @@
+<includeonly>#FORMAT: BEACON
+#PREFIX: http://d-nb.info/gnd/
+#TARGET: {{{querylink}}}
+#VERSION: 0.1
+#HOMEPAGE: https://www.semantic-mediawiki.org/w/index.php?title=Help:BEACON
+#FEED: https://www.semantic-mediawiki.org/w/index.php?title=BEACON&action=render
+#LINK: http://www.w3.org/2000/01/rdf-schema#seeAlso
+#INSTITUTION: Semantic MediaWiki
+#MESSAGE: Person test data in Semantic MediaWiki
+#TIMESTAMP: {{CURRENTTIMESTAMP}}
+#UPDATE: always</includeonly> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon.txt
new file mode 100644
index 00000000..e4d26937
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/s-0025-beacon.txt
@@ -0,0 +1,2 @@
+<includeonly>
+{{{?GND|}}}||{{{?Name|}}}</includeonly>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/skos-import.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/skos-import.txt
new file mode 100644
index 00000000..213056e3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/Fixtures/skos-import.txt
@@ -0,0 +1,33 @@
+http://www.w3.org/2004/02/skos/core#|[http://www.w3.org/TR/skos-reference/skos.rdf Simple Knowledge Organization System (SKOS)]
+ altLabel|Type:Monolingual text
+ broader|Type:Annotation URI
+ broaderTransitive|Type:Annotation URI
+ broadMatch|Type:Annotation URI
+ changeNote|Type:Text
+ closeMatch|Type:Annotation URI
+ Collection|Class
+ Concept|Class
+ ConceptScheme|Class
+ definition|Type:Text
+ editorialNote|Type:Text
+ exactMatch|Type:Annotation URI
+ example|Type:Text
+ hasTopConcept|Type:Page
+ hiddenLabel|Type:String
+ historyNote|Type:Text
+ inScheme|Type:Page
+ mappingRelation|Type:Page
+ member|Type:Page
+ memberList|Type:Page
+ narrower|Type:Annotation URI
+ narrowerTransitive|Type:Annotation URI
+ narrowMatch|Type:Annotation URI
+ notation|Type:Text
+ note|Type:Text
+ OrderedCollection|Class
+ prefLabel|Type:String
+ related|Type:Annotation URI
+ relatedMatch|Type:Annotation URI
+ scopeNote|Type:Text
+ semanticRelation|Type:Page
+ topConceptOf|Type:Page \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php
new file mode 100644
index 00000000..c622b849
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/JsonTestCaseScriptRunnerTest.php
@@ -0,0 +1,510 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\EventHandler;
+use SMW\PropertySpecificationLookup;
+use SMW\SPARQLStore\TurtleTriplesBuilder;
+use SMW\Tests\JsonTestCaseFileHandler;
+use SMW\Tests\JsonTestCaseScriptRunner;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class JsonTestCaseScriptRunnerTest extends JsonTestCaseScriptRunner {
+
+ /**
+ * @var QueryTestCaseProcessor
+ */
+ private $queryTestCaseProcessor;
+
+ /**
+ * @var RdfTestCaseProcessor
+ */
+ private $rdfTestCaseProcessor;
+
+ /**
+ * @var ParserTestCaseProcessor
+ */
+ private $parserTestCaseProcessor;
+
+ /**
+ * @var SpecialPageTestCaseProcessor
+ */
+ private $specialPageTestCaseProcessor;
+
+ /**
+ * @var ParserHtmlTestCaseProcessor
+ */
+ private $parserHtmlTestCaseProcessor;
+
+ /**
+ * @var ApiTestCaseProcessor
+ */
+ private $apiTestCaseProcessor;
+
+ /**
+ * @var RunnerFactory
+ */
+ private $runnerFactory;
+
+ /**
+ * @var EventDispatcher
+ */
+ private $eventDispatcher;
+
+ /**
+ * @see JsonTestCaseScriptRunner::$deletePagesOnTearDown
+ */
+ protected $deletePagesOnTearDown = true;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+ $this->runnerFactory = $utilityFactory->newRunnerFactory();
+
+ $validatorFactory = $utilityFactory->newValidatorFactory();
+ $stringValidator = $validatorFactory->newStringValidator();
+
+ $this->queryTestCaseProcessor = new QueryTestCaseProcessor(
+ $this->getStore(),
+ $validatorFactory->newQueryResultValidator(),
+ $stringValidator,
+ $validatorFactory->newNumberValidator()
+ );
+
+ $this->rdfTestCaseProcessor = new RdfTestCaseProcessor(
+ $this->getStore(),
+ $stringValidator,
+ $this->runnerFactory
+ );
+
+ $this->parserTestCaseProcessor = new ParserTestCaseProcessor(
+ $this->getStore(),
+ $validatorFactory->newSemanticDataValidator(),
+ $validatorFactory->newIncomingSemanticDataValidator( $this->getStore() ),
+ $stringValidator
+ );
+
+ $this->specialPageTestCaseProcessor = new SpecialPageTestCaseProcessor(
+ $this->getStore(),
+ $stringValidator
+ );
+
+ $this->parserHtmlTestCaseProcessor = new ParserHtmlTestCaseProcessor(
+ $validatorFactory->newHtmlValidator()
+ );
+
+ $this->apiTestCaseProcessor = new ApiTestCaseProcessor(
+ $utilityFactory->newMwApiFactory(),
+ $stringValidator
+ );
+
+ $this->eventDispatcher = EventHandler::getInstance()->getEventDispatcher();
+
+ // This ensures that if content is created in the NS_MEDIAWIKI namespace
+ // and an object relies on the MediaWikiNsContentReader then it uses the DB
+ ApplicationFactory::clear();
+ ApplicationFactory::getInstance()->getMediaWikiNsContentReader()->skipMessageCache();
+ DataValueFactory::getInstance()->clear();
+
+ // Reset the Title/TitleParser otherwise a singleton instance holds an outdated
+ // content language reference
+ $this->testEnvironment->resetMediaWikiService( '_MediaWikiTitleCodec' );
+ $this->testEnvironment->resetMediaWikiService( 'TitleParser' );
+
+ // #3414
+ // NameTableAccessException: Expected unused ID from database insert for
+ // 'mw-changed-redirect-target' into 'change_tag_def',
+ $this->testEnvironment->resetMediaWikiService( 'NameTableStoreFactory' );
+
+ $this->testEnvironment->resetPoolCacheById( PropertySpecificationLookup::POOLCACHE_ID );
+ $this->testEnvironment->resetPoolCacheById( TurtleTriplesBuilder::POOLCACHE_ID );
+
+ // Make sure LocalSettings don't interfere with the default settings
+ $this->testEnvironment->withConfiguration(
+ [
+ 'smwgQueryResultCacheType' => false,
+ 'smwgQFilterDuplicates' => false,
+ 'smwgExportResourcesAsIri' => false,
+ 'smwgCompactLinkSupport' => false,
+ 'smwgSparqlReplicationPropertyExemptionList' => [],
+ 'smwgPageSpecialProperties' => [ '_MDAT' ],
+ 'smwgFieldTypeFeatures' => SMW_FIELDT_NONE,
+ 'smwgDVFeatures' => $GLOBALS['smwgDVFeatures'] & ~SMW_DV_NUMV_USPACE,
+ 'smwgCacheUsage' => [
+ 'api.browse' => false
+ ] + $GLOBALS['smwgCacheUsage']
+ ]
+ );
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getTestCaseLocation
+ */
+ protected function getTestCaseLocation() {
+ return __DIR__ . '/TestCases';
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getTestCaseLocation
+ */
+ protected function getRequiredJsonTestCaseMinVersion() {
+ return '2';
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getAllowedTestCaseFiles
+ */
+ protected function getAllowedTestCaseFiles() {
+ return [];
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getDependencyDefinitions
+ */
+ protected function getDependencyDefinitions() {
+ return [
+ 'Maps' => function( $val, &$reason ) {
+
+ if ( !defined( 'SM_VERSION' ) ) {
+ $reason = "Dependency: Maps (or Semantic Maps) as requirement is not available!";
+ return false;
+ }
+
+ list( $compare, $requiredVersion ) = explode( ' ', $val );
+ $version = SM_VERSION;
+
+ if ( !version_compare( $version, $requiredVersion, $compare ) ) {
+ $reason = "Dependency: Required version of Maps ($requiredVersion $compare $version) is not available!";
+ return false;
+ }
+
+ return true;
+ }
+ ];
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::runTestCaseFile
+ *
+ * @param JsonTestCaseFileHandler $jsonTestCaseFileHandler
+ */
+ protected function runTestCaseFile( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ $this->checkEnvironmentToSkipCurrentTest( $jsonTestCaseFileHandler );
+
+ // Setup
+ $this->prepareTest( $jsonTestCaseFileHandler );
+
+ // Before test execution
+ $this->doRunBeforeTest( $jsonTestCaseFileHandler );
+
+ // Run test cases
+ $this->doRunParserTests( $jsonTestCaseFileHandler );
+ $this->doRunSpecialTests( $jsonTestCaseFileHandler );
+ $this->doRunRdfTests( $jsonTestCaseFileHandler );
+ $this->doRunQueryTests( $jsonTestCaseFileHandler );
+ $this->doRunParserHtmlTests( $jsonTestCaseFileHandler );
+ $this->doRunApiTests( $jsonTestCaseFileHandler );
+ }
+
+ /**
+ * @see JsonTestCaseScriptRunner::getPermittedSettings
+ */
+ protected function getPermittedSettings() {
+ parent::getPermittedSettings();
+
+ $elasticsearchConfig = function( $val ) {
+
+ if ( $this->getStore() instanceof \SMWElasticStore ) {
+ $config = $this->getStore()->getConnection( 'elastic' )->getConfig();
+
+ foreach ( $val as $key => $value ) {
+ $config->set( $key, array_merge( $config->get( $key ), $value ) );
+ }
+
+ return $config->toArray();
+ }
+ };
+
+ $this->registerConfigValueCallback( 'smwgElasticsearchConfig', $elasticsearchConfig );
+
+ return [
+ 'smwgNamespacesWithSemanticLinks',
+ 'smwgPageSpecialProperties',
+ 'smwgNamespace',
+ 'smwgExportBCNonCanonicalFormUse',
+ 'smwgExportBCAuxiliaryUse',
+ 'smwgExportResourcesAsIri',
+ 'smwgQMaxSize',
+ 'smwgQMaxDepth',
+ 'smwStrictComparators',
+ 'smwgQSubpropertyDepth',
+ 'smwgQSubcategoryDepth',
+ 'smwgQConceptCaching',
+ 'smwgMaxNonExpNumber',
+ 'smwgDVFeatures',
+ 'smwgEnabledQueryDependencyLinksStore',
+ 'smwgEnabledFulltextSearch',
+ 'smwgFulltextDeferredUpdate',
+ 'smwgFulltextSearchIndexableDataTypes',
+ 'smwgFixedProperties',
+ 'smwgPropertyZeroCountDisplay',
+ 'smwgQueryResultCacheType',
+ 'smwgLinksInValues',
+ 'smwgQFilterDuplicates',
+ 'smwgQueryProfiler',
+ 'smwgEntityCollation',
+ 'smwgSparqlQFeatures',
+ 'smwgQExpensiveThreshold',
+ 'smwgQExpensiveExecutionLimit',
+ 'smwgFieldTypeFeatures',
+ 'smwgCreateProtectionRight',
+ 'smwgParserFeatures',
+ 'smwgCategoryFeatures',
+ 'smwgDefaultOutputFormatters',
+ 'smwgCompactLinkSupport',
+ 'smwgCacheUsage',
+ 'smwgQSortFeatures',
+ 'smwgElasticsearchConfig',
+ 'smwgDefaultNumRecurringEvents',
+
+ // MW related
+ 'wgLanguageCode',
+ 'wgContLang',
+ 'wgLang',
+ 'wgCapitalLinks',
+ 'wgAllowDisplayTitle',
+ 'wgRestrictDisplayTitle',
+ 'wgSearchType',
+ 'wgEnableUploads',
+ 'wgFileExtensions',
+ 'wgDefaultUserOptions',
+ 'wgLocalTZoffset'
+ ];
+ }
+
+ private function prepareTest( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ foreach ( $this->getPermittedSettings() as $key ) {
+ $this->changeGlobalSettingTo(
+ $key,
+ $jsonTestCaseFileHandler->getSettingsFor( $key, $this->getConfigValueCallback( $key ) )
+ );
+ }
+
+ if ( $jsonTestCaseFileHandler->hasSetting( 'smwgFieldTypeFeatures' ) ) {
+ $this->doRunTableSetupBeforeContentCreation();
+ }
+
+ // #2135
+ // On some occasions (e.g. fixed properties) and to setup the correct
+ // table schema, run the creation once before the content is created
+ $pageList = $jsonTestCaseFileHandler->getPageCreationSetupList();
+
+ if ( $jsonTestCaseFileHandler->hasSetting( 'smwgFixedProperties' ) ) {
+ foreach ( $pageList as $page ) {
+ if ( isset( $page['namespace'] ) && $page['namespace'] === 'SMW_NS_PROPERTY' ) {
+ $this->doRunTableSetupBeforeContentCreation( [ $page ] );
+ }
+ }
+ }
+
+ $this->createPagesFrom(
+ $pageList,
+ NS_MAIN
+ );
+ }
+
+ private function doRunTableSetupBeforeContentCreation( $pageList = null ) {
+
+ if ( $pageList !== null ) {
+ $this->createPagesFrom( $pageList );
+ }
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'setupStore' );
+ $maintenanceRunner->setQuiet();
+ $maintenanceRunner->run();
+ }
+
+ private function doRunBeforeTest( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ foreach ( $jsonTestCaseFileHandler->findTasksBeforeTestExecutionByType( 'maintenance-run' ) as $runner => $options ) {
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( $runner );
+ $maintenanceRunner->setQuiet();
+
+ $maintenanceRunner->setOptions(
+ (array)$options
+ );
+
+ $maintenanceRunner->run();
+
+ if ( isset( $options['quiet'] ) && $options['quiet'] === false ) {
+ print_r( $maintenanceRunner->getOutput() );
+ }
+ }
+
+ foreach ( $jsonTestCaseFileHandler->findTasksBeforeTestExecutionByType( 'job-run' ) as $jobType ) {
+ $jobQueueRunner = $this->runnerFactory->newJobQueueRunner( $jobType );
+ $jobQueueRunner->run();
+ }
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ private function doRunParserTests( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ $this->parserTestCaseProcessor->setDebugMode(
+ $jsonTestCaseFileHandler->getDebugMode()
+ );
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'parser' ) as $case ) {
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipFor( $case, $this->connectorId ) ) {
+ continue;
+ }
+
+ $this->parserTestCaseProcessor->process( $case );
+ }
+ }
+
+ private function doRunSpecialTests( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ $this->specialPageTestCaseProcessor->setDebugMode(
+ $jsonTestCaseFileHandler->getDebugMode()
+ );
+
+ $this->specialPageTestCaseProcessor->setTestCaseLocation(
+ $this->getTestCaseLocation()
+ );
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'special' ) as $case ) {
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipFor( $case, $this->connectorId ) ) {
+ continue;
+ }
+
+ $this->specialPageTestCaseProcessor->process( $case );
+ }
+ }
+
+ private function doRunRdfTests( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ // For some reason there are some random failures where
+ // the instance hasn't reset the cache in time to fetch the
+ // property definition which only happens for the SPARQLStore
+
+ // This should not be necessary because the resetcache event
+ // is triggered`
+ $this->eventDispatcher->dispatch( 'exporter.reset' );
+ $this->eventDispatcher->dispatch( 'query.comparator.reset' );
+
+ $this->rdfTestCaseProcessor->setDebugMode(
+ $jsonTestCaseFileHandler->getDebugMode()
+ );
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'rdf' ) as $case ) {
+ $this->rdfTestCaseProcessor->process( $case );
+ }
+ }
+
+ private function doRunQueryTests( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ // Set query parser late to ensure that expected settings are adjusted
+ // (language etc.) because the __construct relies on the context language
+ $this->queryTestCaseProcessor->setQueryParser(
+ ApplicationFactory::getInstance()->getQueryFactory()->newQueryParser()
+ );
+
+ $this->queryTestCaseProcessor->setDebugMode(
+ $jsonTestCaseFileHandler->getDebugMode()
+ );
+
+ $i = 0;
+ $count = 0;
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'query' ) as $case ) {
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipFor( $case, $this->connectorId ) ) {
+ continue;
+ }
+
+ $this->queryTestCaseProcessor->processQueryCase( new QueryTestCaseInterpreter( $case ) );
+ $i++;
+ }
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'concept' ) as $conceptCase ) {
+ $this->queryTestCaseProcessor->processConceptCase( new QueryTestCaseInterpreter( $conceptCase ) );
+ $i++;
+ }
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'format' ) as $case ) {
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipFor( $case, $this->connectorId ) ) {
+ continue;
+ }
+
+ $this->queryTestCaseProcessor->processFormatCase( new QueryTestCaseInterpreter( $case ) );
+ $i++;
+ }
+
+ $count += $jsonTestCaseFileHandler->countTestCasesByType( 'query' );
+ $count += $jsonTestCaseFileHandler->countTestCasesByType( 'concept' );
+ $count += $jsonTestCaseFileHandler->countTestCasesByType( 'format' );
+
+ // Avoid tests being marked as risky when all cases were skipped
+ if ( $i == 0 && $count > 0 ) {
+ $this->markTestSkipped( 'Skipped all assertions for: ' . $this->getName() );
+ }
+ }
+
+ /**
+ * @param JsonTestCaseFileHandler $jsonTestCaseFileHandler
+ */
+ private function doRunParserHtmlTests( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ if ( !$this->parserHtmlTestCaseProcessor->canUse() ) {
+ $this->markTestIncomplete( 'The required resource for the ParserHtmlTestCaseProcessor/HtmlValidator is not available.' );
+ }
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'parser-html' ) as $case ) {
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipFor( $case, $this->connectorId ) ) {
+ continue;
+ }
+
+ $this->parserHtmlTestCaseProcessor->process( $case );
+ }
+ }
+
+ /**
+ * @param JsonTestCaseFileHandler $jsonTestCaseFileHandler
+ */
+ private function doRunApiTests( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ $this->apiTestCaseProcessor->setTestCaseLocation(
+ $this->getTestCaseLocation()
+ );
+
+ foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'api' ) as $case ) {
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipFor( $case, $this->connectorId ) ) {
+ continue;
+ }
+
+ $this->apiTestCaseProcessor->process( $case );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserHtmlTestCaseProcessor.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserHtmlTestCaseProcessor.php
new file mode 100644
index 00000000..5e99a630
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserHtmlTestCaseProcessor.php
@@ -0,0 +1,148 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use SMW\DIWikiPage;
+use SMW\Tests\Utils\UtilityFactory;
+use SMW\Tests\Utils\Validators\HtmlValidator;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author Stephan Gambke
+ */
+class ParserHtmlTestCaseProcessor extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var HtmlValidator
+ */
+ private $htmlValidator;
+
+ /**
+ * @var PageReader
+ */
+ private $pageReader;
+
+ /**
+ * @param HtmlValidator $htmlValidator
+ */
+ public function __construct( HtmlValidator $htmlValidator ) {
+ parent::__construct();
+ $this->htmlValidator = $htmlValidator;
+ $this->pageReader = UtilityFactory::getInstance()->newPageReader();
+ }
+
+ /**
+ * @return boolean
+ */
+ public function canUse() {
+ return $this->htmlValidator->canUse();
+ }
+
+ /**
+ * @param array $case
+ */
+ public function process( array $case ) {
+
+ if ( !isset( $case[ 'subject' ] ) ) {
+ return;
+ }
+
+ if ( isset( $case[ 'about' ] ) ) {
+ $this->setName( $case[ 'about' ] );
+ }
+
+ $this->assertParserHtmlOutputForCase( $case );
+ }
+
+ /**
+ * @param array $case
+ */
+ private function assertParserHtmlOutputForCase( array $case ) {
+
+ if ( !isset( $case[ 'assert-output' ] ) ) {
+ return;
+ }
+
+ $outputText = $this->getOutputText( $case );
+
+ if ( $this->isSetAndTrueish( $case[ 'assert-output' ], 'to-be-valid-html' ) ) {
+ $this->htmlValidator->assertThatHtmlIsValid(
+ $outputText,
+ $case[ 'about' ]
+ );
+ }
+
+ if ( $this->isSetAndTrueish( $case[ 'assert-output' ], 'to-contain' ) ) {
+ $this->htmlValidator->assertThatHtmlContains(
+ $case[ 'assert-output' ][ 'to-contain' ],
+ $outputText,
+ $case[ 'about' ]
+ );
+ }
+
+ if ( $this->isSetAndTrueish( $case[ 'assert-output' ], 'not-contain' ) ) {
+ $this->htmlValidator->assertThatHtmlNotContains(
+ $case[ 'assert-output' ][ 'not-contain' ],
+ $outputText,
+ $case[ 'about' ]
+ );
+ }
+ }
+
+ /**
+ * @param array $case
+ * @return string
+ */
+ private function getOutputText( array $case ) {
+
+ $subject = DIWikiPage::newFromText(
+ $case[ 'subject' ],
+ isset( $case[ 'namespace' ] ) ? constant( $case[ 'namespace' ] ) : NS_MAIN
+ );
+
+ $parserOutput = $this->pageReader->getParserOutputFromEdit(
+ $subject->getTitle()
+ );
+
+ if ( !$this->isSetAndTrueish( $case[ 'assert-output' ], [ 'withOutputPageContext', 'onPageView' ] ) ) {
+ return $parserOutput->getText();
+ }
+
+ $context = new \RequestContext();
+ $context->setTitle( $subject->getTitle() );
+
+ if ( $this->isSetAndTrueish( $case[ 'assert-output' ], 'withOutputPageContext' ) ) {
+ // Ensures the OutputPageBeforeHTML hook is run
+ $context->getOutput()->addParserOutput( $parserOutput );
+ } else {
+ \Article::newFromTitle( $subject->getTitle(), $context )->view();
+ }
+
+ return $context->getOutput()->getHTML();
+
+ }
+
+ /**
+ * @param $array
+ * @param string | string[] $keys
+ * @return bool True if any of the $keys is defined in $array and true-ish
+ */
+ private function isSetAndTrueish( $array, $keys ) {
+
+ $keys = (array)$keys;
+
+ foreach ( $keys as $key ) {
+ if ( isset( $array[ $key ] ) && $array[ $key ] ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserTestCaseProcessor.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserTestCaseProcessor.php
new file mode 100644
index 00000000..42159a6e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/ParserTestCaseProcessor.php
@@ -0,0 +1,247 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use RuntimeException;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\MediaWikiNsContentReader;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class ParserTestCaseProcessor extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var SemanticDataValidator
+ */
+ private $semanticDataValidator;
+
+ /**
+ * @var IncomingSemanticDataValidator
+ */
+ private $incomingSemanticDataValidator;
+
+ /**
+ * @var StringValidator
+ */
+ private $stringValidator;
+
+ /**
+ * @var PageReader
+ */
+ private $pageReader;
+
+ /**
+ * @var SerializerFactory
+ */
+ private $serializerFactory;
+
+ /**
+ * @var boolean
+ */
+ private $debug = false;
+
+ /**
+ * @param Store
+ * @param SemanticDataValidator
+ * @param IncomingSemanticDataValidator
+ * @param StringValidator
+ */
+ public function __construct( $store, $semanticDataValidator, $incomingSemanticDataValidator, $stringValidator ) {
+ $this->store = $store;
+ $this->semanticDataValidator = $semanticDataValidator;
+ $this->incomingSemanticDataValidator = $incomingSemanticDataValidator;
+ $this->stringValidator = $stringValidator;
+ $this->pageReader = UtilityFactory::getInstance()->newPageReader();
+ $this->serializerFactory = \SMW\ApplicationFactory::getInstance()->newSerializerFactory();
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param boolean $debugMode
+ */
+ public function setDebugMode( $debugMode ) {
+ $this->debug = $debugMode;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param array $case
+ */
+ public function process( array $case ) {
+
+ if ( !isset( $case['subject'] ) ) {
+ return;
+ }
+
+ $this->assertSemanticDataForCase(
+ $case
+ );
+
+ $this->assertTextFromParserOutputForCase(
+ $case
+ );
+
+ $this->assertTextFromParsedMsgForCase(
+ $case
+ );
+ }
+
+ private function assertSemanticDataForCase( $case ) {
+
+ // Allows for data to be re-read from the DB instead of being fetched
+ // from the store-id-cache
+ if ( isset( $case['store']['clear-cache'] ) && $case['store']['clear-cache'] ) {
+ $this->store->clear();
+ }
+
+ if ( !isset( $case['assert-store'] ) || !isset( $case['assert-store']['semantic-data'] ) ) {
+ return;
+ }
+
+ $subject = $this->getSubjectFrom( $case, false );
+ $semanticData = $this->store->getSemanticData( $subject );
+
+ if ( $this->debug ) {
+ print_r(
+ $this->serializerFactory->newSemanticDataSerializer()->serialize( $semanticData )
+ );
+ }
+
+ if ( isset( $case['errors'] ) && $case['errors'] !== [] ) {
+ $this->assertNotEmpty(
+ $semanticData->getErrors()
+ );
+ }
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $case['assert-store']['semantic-data'],
+ $semanticData,
+ $case['about']
+ );
+
+ if ( !isset( $case['assert-store']['semantic-data']['incoming'] ) ) {
+ return;
+ }
+
+ $this->incomingSemanticDataValidator->assertThatIncomingDataAreSet(
+ $case['assert-store']['semantic-data']['incoming'],
+ $subject,
+ $case['about']
+ );
+ }
+
+ private function assertTextFromParserOutputForCase( $case ) {
+
+ if ( !isset( $case['assert-output'] ) ) {
+ return;
+ }
+
+ $title = $this->getSubjectFrom( $case )->getTitle();
+
+ $parserOutput = $this->pageReader->getParserOutputFromEdit(
+ $title
+ );
+
+ if ( isset( $case['assert-output']['onOutputPage'] ) && $case['assert-output']['onOutputPage'] ) {
+ $context = new \RequestContext();
+ $context->setTitle( $title );
+ // Ensures the OutputPageBeforeHTML hook is run
+ $context->getOutput()->addParserOutput( $parserOutput );
+ $output = $context->getOutput()->getHtml();
+ } elseif ( isset( $case['assert-output']['onPageView'] ) ) {
+ $parameters = isset( $case['assert-output']['onPageView']['parameters'] ) ? $case['assert-output']['onPageView']['parameters'] : [];
+ $context = \RequestContext::newExtraneousContext(
+ $title,
+ $parameters
+ );
+ \Article::newFromTitle( $title, $context )->view();
+ $output = $context->getOutput()->getHtml();
+ } else {
+ $output = $parserOutput->getText();
+ }
+
+ // Strip HTML comments
+ $output = preg_replace('/<!--(.*)-->/Uis', '', $output );
+
+ if ( isset( $case['assert-output']['to-contain'] ) ) {
+ $this->stringValidator->assertThatStringContains(
+ $case['assert-output']['to-contain'],
+ $output,
+ $case['about']
+ );
+ }
+
+ if ( isset( $case['assert-output']['not-contain'] ) ) {
+ $this->stringValidator->assertThatStringNotContains(
+ $case['assert-output']['not-contain'],
+ $output,
+ $case['about']
+ );
+ }
+ }
+
+ private function assertTextFromParsedMsgForCase( $case ) {
+
+ if ( !isset( $case['assert-msgoutput'] ) ) {
+ return;
+ }
+
+ $mediaWikiNsContentReader = new MediaWikiNsContentReader();
+ $mediaWikiNsContentReader->skipMessageCache();
+
+ $text = $mediaWikiNsContentReader->read( $case['subject'] );
+ $text = wfMessage( 'smw-parse', $text )->parse();
+
+ if ( isset( $case['assert-msgoutput']['to-contain'] ) ) {
+ $this->stringValidator->assertThatStringContains(
+ $case['assert-msgoutput']['to-contain'],
+ $text,
+ $case['about']
+ );
+ }
+
+ if ( isset( $case['assert-msgoutput']['not-contain'] ) ) {
+ $this->stringValidator->assertThatStringNotContains(
+ $case['assert-msgoutput']['not-contain'],
+ $text,
+ $case['about']
+ );
+ }
+ }
+
+ private function getSubjectFrom( $case, $checkExists = true ) {
+
+ $subject = DIWikiPage::newFromText(
+ $case['subject'],
+ isset( $case['namespace'] ) ? constant( $case['namespace'] ) : NS_MAIN
+ );
+
+ $title = $subject->getTitle();
+
+ if ( $title === null ) {
+ throw new RuntimeException( 'Could not create Title object for subject page "' . $case['subject'] . '".' );
+ }
+
+ if ( $checkExists && !$title->exists() ) {
+ throw new RuntimeException( 'Subject page "' . $case['subject'] . '" does not exist.' );
+ }
+
+ return $subject;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseInterpreter.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseInterpreter.php
new file mode 100644
index 00000000..77fa3e7c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseInterpreter.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use SMW\DataTypeRegistry;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDataItem as DataItem;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class QueryTestCaseInterpreter {
+
+ /**
+ * @var array
+ */
+ private $contents;
+
+ /**
+ * @since 2.2
+ *
+ * @param array $contents
+ */
+ public function __construct( array $contents ) {
+ $this->contents = $contents;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return boolean
+ */
+ public function hasCondition() {
+ return isset( $this->contents['condition'] );
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return string
+ */
+ public function getCondition() {
+ return $this->hasCondition() ? $this->contents['condition'] : '';
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return string
+ */
+ public function isAbout() {
+ return isset( $this->contents['about'] ) ? $this->contents['about'] : 'no description';
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return integer
+ */
+ public function getQueryMode() {
+ return isset( $this->contents['parameters']['querymode'] ) ? constant( $this->contents['parameters']['querymode'] ) : \SMWQuery::MODE_INSTANCES;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return integer
+ */
+ public function getLimit() {
+ return isset( $this->contents['parameters']['limit'] ) ? (int)$this->contents['parameters']['limit'] : 100;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return integer
+ */
+ public function getOffset() {
+ return isset( $this->contents['parameters']['offset'] ) ? (int)$this->contents['parameters']['offset'] : 0;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return DIWikiPage|null
+ */
+ public function getSubject() {
+ return isset( $this->contents['subject'] ) ? DIWikiPage::newFromText( $this->contents['subject'] ) : null;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return boolean
+ */
+ public function isFromCache() {
+ return isset( $this->contents['assert-queryresult']['isFromCache'] ) ? (bool)$this->contents['assert-queryresult']['isFromCache'] : null;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return array
+ */
+ public function getExtraPrintouts() {
+
+ $extraPrintouts = [];
+
+ if ( !isset( $this->contents['printouts'] ) || $this->contents['printouts'] === [] ) {
+ return $extraPrintouts;
+ }
+
+ foreach ( $this->contents['printouts'] as $printout ) {
+
+ $label = null;
+
+ if ( strpos( $printout, '#') !== false ) {
+ list( $printout, $label ) = explode( '#', $printout );
+ }
+
+ $extraPrintouts[] = new PrintRequest(
+ PrintRequest::PRINT_PROP,
+ $label,
+ DataValueFactory::getInstance()->newPropertyValueByLabel( $printout )
+ );
+ }
+
+ return $extraPrintouts;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return integer
+ */
+ public function getSortKeys() {
+
+ if ( isset( $this->contents['parameters']['sort'] ) ) {
+
+ if ( is_array( $this->contents['parameters']['sort'] ) ) {
+ return $this->contents['parameters']['sort'];
+ }
+
+ return [ $this->contents['parameters']['sort'] => 'DESC' ];
+ }
+
+ return [];
+ }
+
+ /**
+ * @since 2.3
+ *
+ * @return boolean
+ */
+ public function isRequiredToClearStoreCache() {
+ return isset( $this->contents['store']['clear-cache'] ) && $this->contents['store']['clear-cache'];
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return integer
+ */
+ public function getExpectedCount() {
+ return isset( $this->contents['assert-queryresult']['count'] ) ? (int)$this->contents['assert-queryresult']['count'] : 0;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return DIWikiPage[]
+ */
+ public function getExpectedSubjects() {
+
+ $subjects = [];
+
+ if ( !isset( $this->contents['assert-queryresult']['results'] ) ) {
+ return $subjects;
+ }
+
+ foreach ( $this->contents['assert-queryresult']['results'] as $hashName ) {
+ $subjects[] = DIWikiPage::doUnserialize( str_replace( ' ', '_', $hashName ) );
+ }
+
+ return $subjects;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return DataItem[]
+ */
+ public function getExpectedDataItems() {
+
+ $dataItems = [];
+
+ if ( !isset( $this->contents['assert-queryresult']['dataitems'] ) ) {
+ return $dataItems;
+ }
+
+ foreach ( $this->contents['assert-queryresult']['dataitems'] as $dataitem ) {
+ $dataItems[] = DataItem::newFromSerialization(
+ DataTypeRegistry::getInstance()->getDataItemId( $dataitem['type'] ),
+ $dataitem['value']
+ );
+ }
+
+ return $dataItems;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return DataValues[]
+ */
+ public function getExpectedDataValues() {
+
+ $dataValues = [];
+
+ if ( !isset( $this->contents['assert-queryresult']['datavalues'] ) ) {
+ return $dataValues;
+ }
+
+ foreach ( $this->contents['assert-queryresult']['datavalues'] as $datavalue ) {
+ $dataValues[] = DataValueFactory::getInstance()->newDataValueByProperty(
+ DIProperty::newFromUserLabel( $datavalue['property'] ),
+ $datavalue['value']
+ );
+ }
+
+ return $dataValues;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return integer
+ */
+ public function getExpectedErrorCount() {
+
+ if ( !isset( $this->contents['assert-queryresult']['error'] ) ) {
+ return -1;
+ }
+
+ return $this->contents['assert-queryresult']['error'];
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return string
+ */
+ public function fetchTextFromOutputSubject() {
+
+ if ( !isset( $this->contents['subject'] ) ) {
+ return '';
+ }
+
+ $title = \Title::newFromText( $this->contents['subject'] );
+ $parserOutput = UtilityFactory::getInstance()->newPageReader()->getEditInfo( $title )->output;
+
+ return $parserOutput->getText();
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return array
+ */
+ public function getExpectedFormatOuputFor( $id ) {
+
+ $output = [];
+
+ if ( !isset( $this->contents['assert-output'] ) || !isset( $this->contents['assert-output'][$id] ) ) {
+ return $output;
+ }
+
+ return $this->contents['assert-output'][$id];
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return []
+ */
+ public function getExpectedConceptCache() {
+ return isset( $this->contents['conceptcache'] ) ? $this->contents['conceptcache'] : [];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseProcessor.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseProcessor.php
new file mode 100644
index 00000000..ebe702d6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/QueryTestCaseProcessor.php
@@ -0,0 +1,272 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use SMW\Query\Parser as QueryParser;
+use SMW\Store;
+use SMWQuery as Query;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class QueryTestCaseProcessor extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var QueryParser
+ */
+ private $fileReader;
+
+ /**
+ * @var NumberValidator
+ */
+ private $numberValidator;
+
+ /**
+ * @var boolean
+ */
+ private $debug = false;
+
+ /**
+ * @since 2.2
+ *
+ * @param Store $store
+ */
+ public function __construct( Store $store, $queryResultValidator, $stringValidator, $numberValidator ) {
+ $this->store = $store;
+ $this->queryResultValidator = $queryResultValidator;
+ $this->stringValidator = $stringValidator;
+ $this->numberValidator = $numberValidator;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param QueryParser $queryParser
+ */
+ public function setQueryParser( QueryParser $queryParser ) {
+ $this->queryParser = $queryParser;
+ }
+
+ /**
+ * @since 2.2
+ */
+ public function getStore() {
+ return $this->store;
+ }
+
+ /**
+ * @since 2.2
+ */
+ public function setDebugMode( $debugMode ) {
+ $this->debug = $debugMode;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param QueryTestCaseInterpreter $queryTestCaseInterpreter
+ */
+ public function processQueryCase( QueryTestCaseInterpreter $queryTestCaseInterpreter ) {
+
+ if ( !$queryTestCaseInterpreter->hasCondition() ) {
+ $this->markTestSkipped( 'Found no condition for ' . $queryTestCaseInterpreter->isAbout() );
+ }
+
+ $description = $this->queryParser->getQueryDescription(
+ $queryTestCaseInterpreter->getCondition()
+ );
+
+ $this->printDescriptionToOutput(
+ $queryTestCaseInterpreter->isAbout(),
+ $description
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = $queryTestCaseInterpreter->getQueryMode();
+ $query->setLimit( $queryTestCaseInterpreter->getLimit() );
+
+ $query->setOffset( $queryTestCaseInterpreter->getOffset() );
+ $query->setExtraPrintouts( $queryTestCaseInterpreter->getExtraPrintouts() );
+
+ $query->setSortKeys( $queryTestCaseInterpreter->getSortKeys() );
+ $query->setContextPage( $queryTestCaseInterpreter->getSubject() );
+
+ if ( $queryTestCaseInterpreter->isRequiredToClearStoreCache() ) {
+ $this->getStore()->clear();
+ }
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->printQueryResultToOutput( $queryResult );
+
+ if ( is_string( $queryResult ) ) {
+ return;
+ }
+
+ $this->assertEquals(
+ $queryTestCaseInterpreter->getExpectedCount(),
+ $queryResult->getCount(),
+ 'Failed asserting query result count on ' . $queryTestCaseInterpreter->isAbout()
+ );
+
+ if ( $queryTestCaseInterpreter->getExpectedErrorCount() > -1 ) {
+ $this->numberValidator->assertThatCountComparesTo(
+ $queryTestCaseInterpreter->getExpectedErrorCount(),
+ $queryResult->getErrors(),
+ 'Failed asserting error count ' . $queryTestCaseInterpreter->isAbout()
+ );
+ }
+
+ if ( $queryTestCaseInterpreter->getExpectedErrorCount() > 0 ) {
+ return null;
+ }
+
+ if ( $queryTestCaseInterpreter->isFromCache() !== null ) {
+ $this->assertEquals(
+ $queryTestCaseInterpreter->isFromCache(),
+ $queryResult->isFromCache(),
+ 'Failed asserting isFromCache for ' . $queryTestCaseInterpreter->isAbout()
+ );
+ }
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $queryTestCaseInterpreter->getExpectedSubjects(),
+ $queryResult,
+ $queryTestCaseInterpreter->isAbout()
+ );
+
+ $this->queryResultValidator->assertThatDataItemIsSet(
+ $queryTestCaseInterpreter->getExpectedDataItems(),
+ $queryResult,
+ $queryTestCaseInterpreter->isAbout()
+ );
+
+ $this->queryResultValidator->assertThatDataValueIsSet(
+ $queryTestCaseInterpreter->getExpectedDataValues(),
+ $queryResult,
+ $queryTestCaseInterpreter->isAbout()
+ );
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param QueryTestCaseInterpreter $queryTestCaseInterpreter
+ */
+ public function processConceptCase( QueryTestCaseInterpreter $queryTestCaseInterpreter ) {
+
+ if ( !$queryTestCaseInterpreter->hasCondition() ) {
+ $this->markTestSkipped( 'Found no condition for ' . $queryTestCaseInterpreter->isAbout() );
+ }
+
+ $description = $this->queryParser->getQueryDescription(
+ $queryTestCaseInterpreter->getCondition()
+ );
+
+ $this->printDescriptionToOutput( $queryTestCaseInterpreter->isAbout(), $description );
+
+ $query = new Query(
+ $description,
+ Query::CONCEPT_DESC
+ );
+
+ $query->querymode = $queryTestCaseInterpreter->getQueryMode();
+ $query->setLimit( $queryTestCaseInterpreter->getLimit() );
+ $query->setOffset( $queryTestCaseInterpreter->getOffset() );
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->printQueryResultToOutput( $queryResult );
+
+ $this->assertEquals(
+ $queryTestCaseInterpreter->getExpectedCount(),
+ $queryResult->getCount(),
+ 'Failed asserting query result count on ' . $queryTestCaseInterpreter->isAbout()
+ );
+
+ if ( $queryTestCaseInterpreter->getExpectedErrorCount() > -1 ) {
+ $this->numberValidator->assertThatCountComparesTo(
+ $queryTestCaseInterpreter->getExpectedErrorCount(),
+ $queryResult->getErrors(),
+ 'Failed asserting error count ' . $queryTestCaseInterpreter->isAbout()
+ );
+ }
+
+ foreach ( $queryTestCaseInterpreter->getExpectedConceptCache() as $expectedConceptCache ) {
+
+ $concept = Title::newFromText( $expectedConceptCache['concept'], SMW_NS_CONCEPT );
+
+ $this->getStore()->refreshConceptCache( $concept );
+
+ $this->assertEquals(
+ $expectedConceptCache['count'],
+ $this->getStore()->getConceptCacheStatus( $concept )->getCacheCount(),
+ 'Failed asserting conceptcache count on ' . $queryTestCaseInterpreter->isAbout()
+ );
+ }
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param QueryTestCaseInterpreter $queryTestCaseInterpreter
+ */
+ public function processFormatCase( QueryTestCaseInterpreter $queryTestCaseInterpreter ) {
+
+ if ( $queryTestCaseInterpreter->fetchTextFromOutputSubject() === '' ) {
+ $this->markTestSkipped( 'No content found for ' . $queryTestCaseInterpreter->isAbout() );
+ }
+
+ $textOutput = $queryTestCaseInterpreter->fetchTextFromOutputSubject();
+
+ $this->stringValidator->assertThatStringContains(
+ $queryTestCaseInterpreter->getExpectedFormatOuputFor( 'to-contain' ),
+ $textOutput,
+ $queryTestCaseInterpreter->isAbout()
+ );
+ }
+
+ private function printDescriptionToOutput( $about, $description ) {
+
+ if ( !$this->debug ) {
+ return;
+ }
+
+ print_r( $about . "\n" );
+ print_r( $description );
+ }
+
+ private function printQueryResultToOutput( $queryResult ) {
+
+ if ( is_string( $queryResult ) ) {
+ return print_r( str_replace( [ "&#x0020;", "&#x003A;" ], [ " ", ":" ], $queryResult ) );
+ }
+
+ if ( !$this->debug ) {
+ return;
+ }
+
+ print_r( 'QueryResult' . "\n" );
+ print_r( implode( ',', $queryResult->getQuery()->getErrors() ) );
+ print_r( implode( ',', $queryResult->getErrors() ) );
+ print_r( $queryResult->toArray() );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/README.md b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/README.md
new file mode 100644
index 00000000..79cc9e93
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/README.md
@@ -0,0 +1,612 @@
+# JSONScript
+
+JSONScript is an abstraction from the PHPUnit layer and a best practice approach in Semantic MediaWiki to write integration tests as pseudo `JSONScript` to allow non-developers to review and understand the setup and requirements of its test scenarios.
+
+The `JSON` format was selected to lower the barrier of understanding of what is being tested by using wikitext with a schema like structure to provide an abstraction and hide testing specific PHP language elements.
+
+* [List of available test cases](#TestCases)
+* [Designing an integration test](#Designing_an_integration_test)
+* [Technical notes](#Technical_notes)
+
+<!-- Begin of generated contents by readmeContentsBuilder.php -->
+
+## TestCases
+
+Contains 280 files with a total of 1251 tests:
+
+### A
+* [a-0001.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/a-0001.json) Test API `action=smwbrowse`
+* [a-0002.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/a-0002.json) Test API `action=ask` and `action=askargs` with `api_version` 2 + 3
+* [a-0003.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/a-0003.json) Test API `action=smwbrowse`, `browse=pvalue`
+
+### F
+* [f-0001.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0001.json) Test `format=debug` output
+* [f-0101.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0101.json) Test `format=template` output using unnamed arguments (#885)
+* [f-0102.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0102.json) Test `format=template` output + unicode characters (#988, skip postgres)
+* [f-0103.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0103.json) Test `format=template` with self reference (#988, guard against template self-reference in ask/show query)
+* [f-0104.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0104.json) Test `format=list, ul, ol, template` (#2022,`wgContLang=en`, `wgLang=en`)
+* [f-0105.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0105.json) Test `format=list, ul, ol` on `_qty` property (`wgContLang=en`, `SMW_DV_NUMV_USPACE`)
+* [f-0201.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0201.json) Test `format=table` on boolean table output formatting (#896, #1464)
+* [f-0202.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0202.json) Test `format=table` with sep cell formatting, #495 (`wgContLang=en`,`wgLang=en`)
+* [f-0203.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0203.json) Test `format=table` to sort by category (#1286)
+* [f-0204.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0204.json) Test `format=table` on `_qty` for different positional unit preference (#1329, en)
+* [f-0205.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0205.json) Test `format=table` on `|+align=`/`|+limit`/`|+order`/`|+width=` extra printout parameters (T18571, en)
+* [f-0206.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0206.json) Test `format=table` to display extra property description `_PDESC` (en)
+* [f-0207.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0207.json) Test `format=table` on formatted indent when using */#/: (en)
+* [f-0208.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0208.json) Test `format=table` with `limit=0` (further result links) for user/predefined properties, `mainlabel=-`, `#show` (`wgContLang=en`, `wgLang=es`)
+* [f-0209.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0209.json) Test `format=table` on `_tem`/ `_num` with `LOCAL@...` output (#1591, `wgContLang=es`, `wgLang=en`)
+* [f-0210.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0210.json) Test `format=table` on `_qty` for unit labels with spaces (#1718, `wgContLang=en`, `SMW_DV_NUMV_USPACE`)
+* [f-0211.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0211.json) Test `format=plainlist` with `limit=0` (further result links) for `mainlabel/?#...` (#481)
+* [f-0301.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0301.json) Test `format=category` with template usage (#699, en, skip postgres)
+* [f-0302.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0302.json) Test `format=category` and defaultsort (#699, en)
+* [f-0303.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0303.json) Test `format=category` sort output using a template and DEFAULTSORT (#1459, en)
+* [f-0304.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0304.json) Test `format=category` with identity collation sort (#2065, `smwgEntityCollation=identity`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`)
+* [f-0305.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0305.json) Test `format=category` with uppercase collation sort (#2065, `smwgEntityCollation=uppercase`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`)
+* [f-0306.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0306.json) Test `format=category` with numeric collation sort (same as uppercase, but with numeric sorting) (#2065, `smwgEntityCollation=numeric`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`)
+* [f-0307.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0307.json) Test `format=table` with natural printout sorting (n-asc, n-desc)
+* [f-0308.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0308.json) Test `format=table` with DEFAULTSORT and subject,property sorting
+* [f-0401.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0401.json) Test `format=list` output
+* [f-0402.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0402.json)* [f-0801.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0801.json) Test `format=embedded` output
+* [f-0802.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0802.json) Test `format=template` [[SMW::on/off]] regression using `named args=yes` (#1453, skip-on 1.19)
+* [f-0803.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0803.json) Test `format=template` with `sep`/`named args`/`template arguments` (#972, #2022, #2567)
+* [f-0804.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0804.json) Test `format=embedded` with template transclution
+* [f-0805.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/f-0805.json) Test `format=template`, `format=plainlist` with `#show` and template args (#502)
+
+### P
+* [p-0101.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0101.json) Test in-text annotation for use of restricted properties (#914, `wgContLang=en`, `wgLang=en`)
+* [p-0102.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0102.json) Test in-text annotation on properties with invalid names/characters (#1567, #1638, #1727 `wgContLang=en`)
+* [p-0106.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0106.json) Test #info parser output (#1019, `wgContLang=en`, `wgLang=en`)
+* [p-0107.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0107.json) Test #smwdoc parser output
+* [p-0108.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0108.json) Test `#info`, `#ask` template output (#2347, `wgContLang=en`, `wgLang=en`)
+* [p-0109.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0109.json) Test `#info`, `#ask`/`#show` with error output (`wgContLang=en`, `wgLang=en`)
+* [p-0110.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0110.json) Test tooltip with error output on `_PVUC` (`smwgDVFeatures`, `wgContLang=en`, `wgLang=en`)
+* [p-0111.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0111.json) Test reserved property names
+* [p-0202.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0202.json) Test #set parser to use template for output (#1146, en)
+* [p-0203.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0203.json) Test #set parser in combination with #subobject and template output (#1067, regression check)
+* [p-0204.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0204.json) Test #set parser to produce error output (#870, en, verify that #set calls do not affect each other with previous errors)
+* [p-0205.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0205.json) Test #set/#ask recursive annotation support (#711, #1055, recursive annotation using import-annotation=true via template)
+* [p-0206.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0206.json) Test #show parser on inverse printrequest (#1222, #1223)
+* [p-0207.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0207.json) Test that undeclared properties with references remain after a `rebuildData` run (#1216, en)
+* [p-0208.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0208.json) Test `#set` for various `_num` values without explicit precision (3 digit implicit), with/without leading zero, different printouts, negative numbers (#753, en, `smwgMaxNonExpNumber`)
+* [p-0209.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0209.json) Test `#set` for various `_qty` values without explicit precision (3 digit implicit), with/without leading zero, and different printouts (#753, en, `smwgMaxNonExpNumber`)
+* [p-0210.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0210.json) Test `#set_recurring_event` (`wgContLang=en`, `wgLang=en`)
+* [p-0211.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0211.json) Test `#set`/`#subobject` to import annotation via `@json` syntax (`wgContLang=en`, `wgLang=en`)
+* [p-0212.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0212.json) Test `@@@` in-text annotation syntax (#1855, #1875 `wgContLang=en`, `wgLang=en`)
+* [p-0301.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0301.json) Test #subobject category annotation (#1172)
+* [p-0302.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0302.json) Test #subobject parser to use invalid assignments and create `_ERRC` (#1299, en)
+* [p-0303.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0303.json) Test `#subobject` and `#set` parser on values with spaces (`wgContLang=en`, `wgLang=en`)
+* [p-0401.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0401.json) Test annotations with disabled capital links (#673, `wgCapitalLinks=false`)
+* [p-0402.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0402.json) Test in-text parsing for double colon annotation such as `::::` or `:::` (#1066, #1075, en)
+* [p-0403.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0403.json) Test in-text annotations being disabled for when Factbox contains extra `[[ ... ]]` (#1126)
+* [p-0404.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0404.json) Test in-text annonation on different category colon identifier
+* [p-0405.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0405.json) Test in-text annotation via template and manual redirect (#895)
+* [p-0406.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0406.json) Test in-text annotation for unrestricted template parse using `import-annotation=true` (#1055)
+* [p-0407.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0407.json) Test in-text annotation for a redirect that is pointing to a deleted target (#1105)
+* [p-0408.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0408.json) Test in-text annotation for multiple property assignment using non-strict parser mode (#1252, en)
+* [p-0409.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0409.json) Test in-text annotation for `_rec`/`_mlt_rec` (+ subobject) for when record type points to another record type (`wgContLang=en`, `wgLang=en`)
+* [p-0410.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0410.json) Test in-text annotation on `_num`/`_tem`/`_qty` type with denoted precision (`_PREC`) and/or `-p<num>` printout precision marker (#1335, en)
+* [p-0411.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0411.json) Test in-text annotation (and #subobject) using a monolingual property (#1344, en)
+* [p-0412.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0412.json) Test in-text annotation for `_boo` datatype (`wgContLang=ja`, `wgLang=ja`)
+* [p-0413.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0413.json) Test in-text annotation for different `_dat` input/output (en, skip virtuoso, `smwgDVFeatures`)
+* [p-0414.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0414.json) Test in-text annotation/free format for `_dat` datatype (#1389, #1401, en, `smwgDVFeatures`)
+* [p-0415.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0415.json) Test in-text annotation on `_tem` with display unit preference (en)
+* [p-0416.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0416.json) Test in-text annotation with DISPLAYTITLE (#1410, #1611, `wgRestrictDisplayTitle`, `wgContLang=en`, `wgLang=en`)
+* [p-0417.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0417.json) Test in-text annotation for `Allows pattern` to match regular expressions (en)
+* [p-0418.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0418.json) Test in-text annotation using `_SERV` as provide service links (en)
+* [p-0419.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0419.json) Test in-text annotation for `_PVUC` to validate uniqueness (`smwgDVFeatures`)
+* [p-0420.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0420.json) Test in-text annotation for `_dat` using JL/GR annotated values (en, `smwgDVFeatures`)
+* [p-0421.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0421.json) Test in-text annotation with combined constraint validation `_PVUC` and `_PVAL` (`smwgDVFeatures`)
+* [p-0422.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0422.json) Test in-text annotation `_dat` on partial dates (#2076, `wgContLang=en`, `wgLang=en`)
+* [p-0423.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0423.json) Test in-text annotation / `#ask` (#MEDIAWIKI, #LOCL) output for `_dat` datatype (#1545, `wgContLang=en`, `wgLang=ja`)
+* [p-0424.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0424.json) Test in-text annotation for `_boo` datatype using `LOCL` (`wgContLang=en`, `wgLang=fr`, skip-on 1.25.6)
+* [p-0425.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0425.json) Test in-text annotation on `_tem`/ `_num` with different page content language (#1591, `wgContLang=es`, `wgLang=en`)
+* [p-0426.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0426.json) Test in-text annotation for `_num` on big/small numbers/scientific notation (`wgContLang=fr`, `wgLang=en`)
+* [p-0427.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0427.json) Test in-text annotation with DISPLAYTITLE / `foaf` to check on upper vs. lower case (`wgRestrictDisplayTitle`, `wgContLang=en`, `wgLang=en`)
+* [p-0428.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0428.json) Test `_TYPE` annotations on different content language (`wgContLang=fr`, `wgLang=en`)
+* [p-0429.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0429.json) Test in-text `_dat` annotation with time offset, time zone, am/pm (`wgContLang=en`, `wgLang=en`)
+* [p-0430.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0430.json) Test in-text annotation for `_eid` type (`#nowiki`) (`wgContLang=en`, `wgLang=en`)
+* [p-0431.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0431.json) Test in-text annotation `_rec` and `|+index` (`wgContLang=en`, `wgLang=en`)
+* [p-0432.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0432.json) Test in-text annotation for `_ref_rec` type (#1808, `wgContLang=en`, `wgLang=en`)
+* [p-0433.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0433.json) Test in-text annotation `::` with left pipe (#1747, `wgContLang=en`)
+* [p-0434.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0434.json) Test printrequest property chaining `|?Foo.Bar` (#1824, `wgContLang=en`, `wgLang=en`)
+* [p-0435.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0435.json) Test in-text annotation using `_txt` type with 255+ char, `#ask` to produce reduced length (#1878, `wgContLang=en`, `wgLang=en`)
+* [p-0436.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0436.json) Test in-text annotation with `_PPLB` [preferred property label] (#1879, `wgContLang=en`, `wgLang=en`)
+* [p-0437.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0437.json) Test in-text annotation with preferred property label/`_PPLB` (#1879, `wgContLang=en`, `wgLang=ja`)
+* [p-0438.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0438.json) Test in-text annotation with preferred property label/DISPLAYTITLE on user/predefined properties (`wgContLang=es`, `wgLang=de`, `wgRestrictDisplayTitle=false`)
+* [p-0439.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0439.json) Test in-text annotation using '_txt'/'_wpg' type / UTF encoding (`wgContLang=en`, `wgLang=en`)
+* [p-0440.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0440.json) Test in-text annotation `_mlt_rec` (Monolingual text) with `|+lang`/`|+order` parameter (`wgContLang=en`, `wgLang=en`)
+* [p-0441.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0441.json) Test in-text `_txt` 00 string/loose comparison (#2061)
+* [p-0442.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0442.json) Test in-text `#REDIRECT` to verify target subobject isn't removed (#, `wgContLang=en`, `wgLang=en`)
+* [p-0443.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0443.json) Test conditions and strict constraint validations for uniqueness `_PVUC` (#1463, `wgContLang=en`, `wgLang=en`, `smwgDVFeatures`)
+* [p-0444.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0444.json) Test in-text annotation with links in values (#2153, `wgContLang=en`)
+* [p-0445.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0445.json) Test in-text annotation for `_ref_rec` type with errors (#..., `wgContLang=en`)
+* [p-0446.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0446.json) Test in-text annotation `_uri`/`_ema`/`_tel` with spaces/underscore (`wgContLang=en`)
+* [p-0447.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0447.json) Test in-text annotation with IRI export (#2188, `smwgExportResourcesAsIri=true`, `wgContLang=ru`, `wgLang=en`)
+* [p-0448.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0448.json) Test in-text legacy `:=` annotation style (#2153, `wgContLang=en`)
+* [p-0449.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0449.json) Test in-text legacy `:=` and `::` annotation style with enabled links in values (#2153, `wgContLang=en`)
+* [p-0450.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0450.json) Test in-text annotation with invisible chars (`wgContLang=en`)
+* [p-0451.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0451.json) Test in-text `_dat` datatype, time zone, and JD output (#2454, `wgContLang=en`, `wgLang=en`, `smwgDVFeatures=SMW_DV_TIMEV_CM`)
+* [p-0452.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0452.json) Test in-text `_txt` datatype in combination with an "Allows value" output (#2342, `wgContLang=en`, `wgLang=en`)
+* [p-0453.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0453.json) Test in-text `_dat` annotation with `#LOCL#TO` (`wgLocalTZoffset`, `wgContLang=en`, `wgLang=en`)
+* [p-0454.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0454.json) Test in-text annotation with enabled links in values on `&#91;`, `&#93;` (#2671, `wgContLang=en`)
+* [p-0455.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0455.json) Test paser/in-text annotation with unstripped tags (nowiki etc.) (`SMW_PARSER_UNSTRIP`)
+* [p-0456.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0456.json) Test #subobject with assigned sortkey, default order etc.
+* [p-0457.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0457.json) Test named subobject caption display (#2895)
+* [p-0458.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0458.json) Test keyword type `_keyw`
+* [p-0459.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0459.json) Test keyword type `_keyw` with a formatter schema (`smwgCompactLinkSupport`)
+* [p-0460.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0460.json) Test in-text `_num`, `_qty` in combination with an "Allows value" range, bounds
+* [p-0501.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0501.json) Test `#concept` on predefined property (`wgContLang=en`, `wgLang=es`)
+* [p-0502.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0502.json) Test in-text annotation allows value list (#2295, `wgContLang=en`, `wgLang=en`)
+* [p-0503.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0503.json) Test in-text annotation `_uri` on valid/invalid scheme
+* [p-0701.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0701.json) Test to create inverted annotation using a #ask/template combination (#711, `import-annotation=true`)
+* [p-0702.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0702.json) Test #ask with `format=table` on inverse property/printrequest (#1270, #1360)
+* [p-0703.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0703.json) Test `#ask` on `format=table` using different printrequest label output (#1270, `wgContLang=en`, `wgLang=en`)
+* [p-0704.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0704.json) Test `#ask` sanitization of printrequest labels to avoid XSS injection (`wgContLang=en`, `wgLang=en`)
+* [p-0705.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0705.json) Test `#ask`/ NS_FILE option (`wgContLang=en`, `wgLang=en`, `wgEnableUploads`, `wgFileExtensions`, 'wgDefaultUserOptions')
+* [p-0706.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0706.json) Test `#ask` on `format=template` with message parse (`wgContLang=en`, `wgLang=en`)
+* [p-0707.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0707.json) Test `#ask` with enabled execution limit (`wgContLang=en`, `wgLang=en`, `smwgQExpensiveThreshold`, `smwgQExpensiveExecutionLimit`)
+* [p-0708.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0708.json) Test `#ask` NS_FILE and DISPLAYTITLE (`wgContLang=en`, `wgLang=en`, `wgEnableUploads`, `wgFileExtensions`, 'wgDefaultUserOptions', `wgRestrictDisplayTitle`)
+* [p-0709.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0709.json) Test #ask with `format=table` on inverse property, property path
+* [p-0710.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0710.json) Test `#ask` with `[[Category::Foo]]`
+* [p-0711.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0711.json) Test `#ask` with `||` condition (#3473)
+* [p-0901.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0901.json) Test #ask on moved redirected subject (#1086)
+* [p-0902.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0902.json) Test #ask on failed queries to produce a `_ERRC` (#1297, en)
+* [p-0903.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0903.json) Test #ask on redirected printrequest (#1290, en)
+* [p-0904.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0904.json) Test #ask with subject redirected to different NS (en)
+* [p-0905.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0905.json) Test `#ask` query-in-query construct (`_sobj`/`_dat`/`_num`) (`wgContLang=en`, `wgLang=en`)
+* [p-0906.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0906.json) Test `#ask` on category/property hierarchy with circular reference (#1713, `wgContLang=en`, `wgLang=en`, 'smwgEnabledQueryDependencyLinksStore', skip virtuoso)
+* [p-0907.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0907.json) Test the QueryResult cache feature (#1251, `wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`)
+* [p-0908.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0908.json) Test the QueryResult cache feature with different `|+lang`/`|+order` prinrequest parameters (#1251, `wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`)
+* [p-0909.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0909.json) Test the description optimization (`wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`, `smwgQFilterDuplicates=true`, `smwgQueryProfiler`)
+* [p-0910.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0910.json) Test `#ask` to highlight (`#-hl`) search token in result set (#..., `wgContLang=en`, `wgLang=en`)
+* [p-0911.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0911.json) Test the `_ASK` profile (#2270, `smwgQueryProfiler`, `smwgQueryResultCacheType`)
+* [p-0912.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0912.json) Test `#ask` with (`#-raw`) formatter using `#set` (#..., `wgContLang=en`, `wgLang=en`)
+* [p-0913.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0913.json) Test `#ask` with (`#-raw`) formatter with links in values (#..., `wgContLang=en`, `wgLang=en`)
+* [p-0914.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0914.json) Test the description optimization on `_ref_rec` type with property chain query/sort (`wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`, `smwgQFilterDuplicates=true`, `smwgQueryProfiler`)
+* [p-0915.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0915.json) Test category redirect (`SMW_CAT_REDIRECT`)
+* [p-0916.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-0916.json) Test `_ref_rec` with a `_eid` field (#2985)
+* [p-1000.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1000.json) Test property page with redirect(synonym)/displayTitle (`wgContLang=en`, `wgLang=en`, `wgAllowDisplayTitle`)
+* [p-1001.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1001.json) Test property page with parameters (#2479, `wgContLang=en`, `wgLang=en`)
+* [p-1002.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1002.json) Test property page with improper assignment list (`wgContLang=en`, `wgLang=en`)
+* [p-1003.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1003.json) Test property restriction on annotation and #ask (`wgContLang=en`, `wgLang=en`, `smwgCreateProtectionRight`)
+* [p-1004.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1004.json) Test different default output formatter `_dat` (`smwgDefaultOutputFormatters`)
+* [p-1005.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1005.json) Test property page with parameters/sort
+* [p-1006.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1006.json) Test property page sorting (`wgRestrictDisplayTitle`, `smwgEntityCollation`)
+* [p-1007.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/p-1007.json) Test sorting on Pages will not exclude non-existent pages from result (#540)
+
+### Q
+* [q-0101.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0101.json) Test `_txt` query for simple assignments, NS_HELP, and special chars
+* [q-0102.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0102.json) Test `_txt` for `~*` regex queries to validate correct escape pattern as applied in the `QueryEngine`
+* [q-0103.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0103.json) Test `_txt` for `~*` regex query with the condition to include the `\` escape character (skip sqlite, postgres)
+* [q-0104.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0104.json) Test `_txt`/`~` with enabled full-text search support (only enabled for MySQL, SQLite)
+* [q-0105.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0105.json) Test `_wpg`/`~` with enabled full-text search support (only enabled for MySQL, SQLite, `SMW_FT_WIKIPAGE`)
+* [q-0106.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json) Test `_txt`/`~` with enabled full-text search support on fixed user property (only enabled for MySQL, SQLite, `smwgFixedProperties`)
+* [q-0201.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0201.json) Test `_CONC` queries (skip virtuoso)
+* [q-0202.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0202.json) Test `_CONC` for guarding against circular/self-reference which otherwise would fail with 'Maximum function nesting level ... reached, aborting' (#945, skip virtuoso)
+* [q-0203.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0203.json) Test `_CONC` to use `CONCEPT_CACHE_ALL` (#1050, skip all SPARQL repository)
+* [q-0204.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0204.json) Test `_CONC` on predefined inverse query and subobject inverse query (#1096, skip virtuoso)
+* [q-0301.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0301.json) Test `_IMPO` queries for imported foaf vocabulary (#891, en)
+* [q-0401.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0401.json) Test `_SUBP` on a simple 'family' subproperty hierarchy example query (#1003, skip virtuoso)
+* [q-0402.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0402.json) Test `_SUBP` to map DC imported vocabulary with MARC 21 bibliographic terms (#1003, http://www.loc.gov/marc/bibliographic/bd20x24x.html)
+* [q-0501.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0501.json) Test `_qty` queries for custom unit (km²/°C) property value assignments
+* [q-0502.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0502.json) Test `_qty` range queries using non strict comparators (`smwStrictComparators=false`)
+* [q-0503.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0503.json) Test `_qty` on positional unit preference in query condition (#1329, `smwStrictComparators=false`)
+* [q-0601.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0601.json) Test `_wpg` for property chain query queries
+* [q-0602.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0602.json) Test `_wpg` sort query with #subobject annotated @sortkey content
+* [q-0603.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0603.json) Test `_wpg` queries for various conditions using #set annotated content
+* [q-0604.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0604.json) Test `_wpg` queries to resolve property/values redirects (#467, skip virtuoso)
+* [q-0605.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0605.json) Test `_wpg` regex search (`!~/~*/~?`) queries (#679)
+* [q-0606.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0606.json) Test `_wpg`/`_num`/`_txt` using subqueries (#466, #627, #625)
+* [q-0607.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0607.json) Test `_wpg`/`_dat`/`_num`/`_txt` subquery example
+* [q-0608.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0608.json) Test `_wpg` for single value approximate (`~/!~`) queries (#1246)
+* [q-0609.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0609.json) Test `_wpg` for single value approximate (`~/!~`) queries with conjunctive category hierarchy (#1246, en, skip virtuoso)
+* [q-0610.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0610.json) Test `_wpg` range queries (#1291, `smwStrictComparators=false`, skip virtuoso)
+* [q-0611.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0611.json) Test `_wpg` namespace any value queries (#1301, en)
+* [q-0612.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0612.json) Test `_wpg` object value that contains `=` (equals sign) (#640, #710, #1542, #1645, `wgContLang=en`, `wgLang=en`)
+* [q-0613.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0613.json) Test single value (`~/!~`/`<`/`>`) queries on namespaced entity (#1652, `NS_HELP`, `smwStrictComparators=false`, skip-on virtuoso)
+* [q-0614.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0614.json) Test query with category hierarchy depth (#2662, `wgContLang=en`, `smwgQSubpropertyDepth`, `smwgQSubcategoryDepth`, skip virtuoso)
+* [q-0615.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0615.json) Test query with property hierarchy depth (#2662, `wgContLang=en`, `smwgQSubpropertyDepth`, `smwgQSubcategoryDepth`, skip virtuoso)
+* [q-0616.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0616.json) Test `in:` syntax on `_txt`, `_dat`, and `_num` values
+* [q-0617.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0617.json) Test range `<>` syntax on `_num` (float,double), `_dat` (millisec) values (`smwStrictComparators=true`)
+* [q-0618.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0618.json) Test deep subqueries (Friends of friends) (`smwgQMaxDepth`)
+* [q-0619.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0619.json) Test `_wpg` user case (#2982)
+* [q-0620.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0620.json) Test `_wpg` and category using subquery construct
+* [q-0621.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0621.json) Test `_wpg` and namespace using subquery construct
+* [q-0622.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0622.json) Test query with category hierarchy
+* [q-0701.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0701.json) Test `_uri` with some annotation/search pattern (T45264, #679)
+* [q-0702.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0702.json) Test `_uri` with additional annotation/search (#1129)
+* [q-0703.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0703.json) Test to map `Foaf` property from back-end / using a localized predefined property `A le type@fr` (en)
+* [q-0704.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0704.json) Test `_uri` long URL (255+) (#1872)
+* [q-0801.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0801.json) Test `_INST` query (#1004, en)
+* [q-0802.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0802.json) Test `_INST`/`_SUBC` queries (#1005, en, skip virtuoso)
+* [q-0803.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0803.json) Test `_INST`/ Nested category annotation (#1012, en, skip virtuoso) category hierarchy queries
+* [q-0804.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0804.json) Test `_INST` with namespace prefix
+* [q-0901.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0901.json) Test `_wpg`/`_txt` on various disjunction, conjunction queries (#19, #1060, #1056, #1057)
+* [q-0902.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0902.json) Test `_txt` to correctly apply parentheses for somehting like (a OR b OR c) AND d (#556)
+* [q-0903.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0903.json) Test `_wpg`/`_num`/`_txt` for disjunction OR || (T31866, #1059, en)
+* [q-0904.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0904.json) Test `_wpg`/`_txt` disjunction in connection with property hierarchies (#1060, en, skip virtuoso)
+* [q-0905.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0905.json) Test `_wpg`/`_txt` conjunction queries (#1362, #1060)
+* [q-0906.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0906.json) Test `_wpg`/`_txt` with enabled `SMW_FIELDT_CHAR_NOCASE` (#1912, `smwgFieldTypeFeatures`)
+* [q-0907.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0907.json) Test `_txt`/`_uri` with enabled `SMW_FIELDT_CHAR_LONG | SMW_FIELDT_CHAR_NOCASE` (#1912, #2499, `smwgFieldTypeFeatures`)
+* [q-0908.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0908.json) Test `_wpg`/`_txt`/`_uri` on enabled `SMW_FIELDT_CHAR_LONG | SMW_FIELDT_CHAR_NOCASE` with `like:/nlike:` (#1912, #2499, `smwgFieldTypeFeatures`, `smwgSparqlQFeatures`)
+* [q-0909.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0909.json) Test `_txt/`_uri`/`_num`/`_dat` with `!...` (NEQ)
+* [q-0910.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0910.json) Test `SMW_QSORT_UNCONDITIONAL` (`smwgQSortFeatures`, skip-on all SPARQL repositories, postgres)
+* [q-0911.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-0911.json) Test `_wpg` empty chain/subquery (AND, OR)
+* [q-1002.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1002.json) Test `_dat` range for non strict comparators (#285, `smwStrictComparators=false`, skip virtuoso)
+* [q-1003.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1003.json) Test `_dat` range for strict comparators (#285, `smwStrictComparators=true`, skip virtuoso)
+* [q-1004.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1004.json) Test `_dat` range for `~`/`!~` comparators (#1178, `smwStrictComparators=false`, skip virtuoso)
+* [q-1101.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1101.json) Test _rec for non strict comparators queries (`smwStrictComparators=false`)
+* [q-1102.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1102.json) Test `_rec` queries in combination with `_dat` `~/!~` search pattern (#1178, `smwStrictComparators=false`, skip virtuoso)
+* [q-1103.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1103.json) Test `_rec` using some additional search pattern (#1189, en)
+* [q-1104.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1104.json) Test `_rec` to find correct target for redirected property (#1244, en)
+* [q-1105.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1105.json) Test `_rec` in combination with named subobject (T49472, #1300, en, `smwStrictComparators=false`)
+* [q-1106.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1106.json) Test `_rec` with `~/!~` comparators on allowed values (#1207, `smwStrictComparators=false`)
+* [q-1107.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1107.json) Test `_rec`/`_mlt_rec`(`_PDESC`) to use property chaining (`wgContLang=en`)
+* [q-1108.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1108.json) Test conditions and constraint validations for allowed values `_LIST` and uniqueness `_PVUC` (#1207, `wgContLang=en`, `wgLang=en`)
+* [q-1200.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1200.json) Test `_wpg/`_txt` with `~*` and `.../...` queries (ES only)
+* [q-1201.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1201.json) Test `_wpg/`_txt` with `not:`/`!~` queries (ES only)
+* [q-1202.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1202.json) Test `_wpg/`_txt` with `not:`/`!~` queries (ES only, `raw.text`)
+* [q-1203.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1203.json) Test `_wpg/`_txt` with `in:/phrase:` queries (ES only)
+* [q-1204.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1204.json) Test `!` category queries (ES only, `smwgQSubcategoryDepth`)
+* [q-1205.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1205.json) Test `[[Has subobject::!]]` / `[[Has subobject::!+]]` (ES only)
+* [q-1206.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1206.json) Test `cjk.best.effort.proximity.match` (ES only)
+* [q-1300.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/q-1300.json) Test `_geo` (requires Maps)
+
+### R
+* [r-0001.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0001.json) Test RDF output for `_txt`/`_wpg`/`_dat` (#881)
+* [r-0002.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0002.json) Test RDF output for redirected pages (#882)
+* [r-0003.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0003.json) Test RDF output for imported foaf vocabulary (#884, en)
+* [r-0004.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0004.json) Test RDF output generation for `_INST`/`_SUBC` pages (#922, en)
+* [r-0005.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0005.json) Test RDF wiki-info output (#928, en)
+* [r-0006.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0006.json) Test RDF output generation for pages that contain `_rec` annotations (#1285, #1275)
+* [r-0007.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0007.json) Test RDF output for imported dc/gna vocabulary, owl:AnnotationProperty, owl:DatatypeProperty, owl:ObjectProperty, Equivalent URI (#795, `wgRestrictDisplayTitle`, en)
+* [r-0008.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0008.json) Test RDF output generation on pages that contain incoming error annotations (`wgContLang=en`, `wgLang=es`, syntax=rdf/turtle)
+* [r-0009.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0009.json) Test RDF output generation that contain a monolingual text annotations `_PDESC` (`wgContLang=en`, `wgLang=es`, syntax=rdf/turtle)
+* [r-0010.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0010.json) Test RDF output on canonical entities (`wgContLang=fr`, `wgLang=es`, syntax=rdf/turtle)
+* [r-0011.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0011.json) Test RDF output generation `skos` import/`skos:altLabel` as Monolingual text (`wgContLang=en`, `wgLang=en`)
+* [r-0012.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0012.json) Test RDF output generation on SubSemanticData traversal (#2177, `wgContLang=en`, `wgLang=en`)
+* [r-0013.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0013.json) Test RDF output generation `_uri`/`_ema`/`_tel` with spaces/underscore (`wgContLang=en`, `wgLang=en`)
+* [r-0014.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0014.json) Test RDF output generation on non-latin URI/IRI export (#2188, `smwgExportResourcesAsIri=false`, `wgContLang=ru`, `wgLang=en`)
+* [r-0015.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0015.json) Test RDF output generation on non-latin URI/IRI export (#2188, `smwgExportResourcesAsIri=true`, `wgContLang=ru`, `wgLang=en`)
+* [r-0016.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0016.json) Test RDF output generation with special characters (#2188, `smwgExportResourcesAsIri=false`, `wgContLang=en`, `wgLang=en`)
+* [r-0017.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0017.json) Test RDF output generation with special characters (#2188, `smwgExportResourcesAsIri=true`, `wgContLang=en`, `wgLang=en`)
+* [r-0018.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0018.json) Test RDF output generation with special characters (`smwgExportResourcesAsIri=true`, `wgContLang=en`, `wgLang=en`)
+* [r-0019.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0019.json) Test RDF output on `swivt:sort` with enabled collation (#2065, `smwgEntityCollation=uppercase`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`, `wgContLang=en`, `wgLang=en`)
+* [r-0020.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/r-0020.json) Test RDF output on `/` in porperty name (#3134)
+
+### S
+* [s-0001.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0001.json) Test output of `Special:Properties` (`wgContLang=en`, skip-on sqlite)
+* [s-0002.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0002.json) Test output from `Special:SearchByProperty` for `_num`, `_txt`, `_tel` (#1728, #2009, `wgContLang=en`, `wgLang=en`, skip-on sqlite, postgres)
+* [s-0003.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0003.json) Test `Special:Ask` output for `format=rdf`/`format=json`/DISPLAYTITLE (#1453, #1619, `wgRestrictDisplayTitle`, `wgContLang=en`)
+* [s-0004.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0004.json) Test `Special:Browse` output for `_dat` (`wgContLang=en`, `wgLang=ja`)
+* [s-0005.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0005.json) Test `Special:Browse` output for `_dat`, '_REDI' (`wgContLang=en`, `wgLang=en`, `smwgDVFeatures=SMW_DV_TIMEV_CM | SMW_DV_WPV_DTITLE`, `wgRestrictDisplayTitle=false`)
+* [s-0006.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0006.json) Test output of `Special:WantedProperties` (`wgContLang=en`, `wgLang=en`, skip-on sqlite)
+* [s-0007.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0007.json) Test output of `Special:UnusedProperties` (`wgContLang=en`, `wgLang=en`, skip-on sqlite, 1.19)
+* [s-0008.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0008.json) Test `Special:Browse` output for `_dat`, `_boo`, `_sobj`, `_uri` (`wgContLang=en`, `wgLang=es`, skip-on 1.25.6)
+* [s-0009.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0009.json) Test output in `Special:Search` for SMWSearch (`wgLanguageCode=en`, `wgContLang=en`, `wgSearchType=SMWSearch`)
+* [s-0010.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0010.json) Test output from `Special:SearchByProperty` / `_dat` (#1922, `wgContLang=en`, `wgLang=es`, skip-on sqlite)
+* [s-0011.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0011.json) Test `Special:Ask` output `#ask` intro/outro link/template parse (`wgContLang=en`, `wgLang=en`)
+* [s-0012.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0012.json) Test `Special:Ask` output `#ask` image/upload (#2009, `wgContLang=en`, `wgLang=en`, `wgEnableUploads`, `wgFileExtensions`)
+* [s-0013.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0013.json) Test `Special:Browse` output preferred label (`wgContLang=en`, `wgLang=es`)
+* [s-0014.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0014.json) Test `Special:Browse` with special characters `%'"&` (`wgContLang=en`, `wgLang=es` )
+* [s-0015.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0015.json) Test `Special:Ask` output for `_txt` with formatted text (#..., `wgContLang=en`, `wgLang=en`)
+* [s-0016.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0016.json) Test `Special:Ask` to produce correct printout position for `+|...` parameters (`wgContLang=en`, `wgLang=en`)
+* [s-0017.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0017.json) Test `Special:Types` (`wgContLang=en`, `wgLang=en`)
+* [s-0018.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0018.json) Test `Special:Ask` common output (`wgContLang=en`, `wgLang=en`)
+* [s-0019.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0019.json) Test output of `Special:WantedProperties` on unapproved property (`wgContLang=en`, `wgLang=en`, `smwgCreateProtectionRight`)
+* [s-0020.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0020.json) Test `Special:Ask` with `format=json` output (`wgContLang=en`, `wgLang=en`)
+* [s-0021.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0021.json) Test `format=table` on `Special:Ask` with `headers=plain` (#2702, `wgContLang=en`, `wgLang=en`)
+* [s-0022.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0022.json) Test `format=csv` output via `Special:Ask` (`wgContLang=en`, `wgLang=en`)
+* [s-0023.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0023.json) Test `Special:Browse` output category (`wgContLang=en`, `wgLang=en`)
+* [s-0024.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0024.json) Test `Special:Browse` with compact links (`smwgCompactLinkSupport`)
+* [s-0025.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0025.json) Test `format=templatefile` (with `_eid`) output via `Special:Ask`
+* [s-0026.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0026.json) Test output from `Special:PageProperty` (with `_dat`)
+* [s-0027.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0027.json) Test `format=feed` output via `Special:Ask` (`wgEnableUploads`, `wgFileExtensions`, `wgRestrictDisplayTitle`)
+* [s-0028.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0028.json) Test `Special:Browse` limited value list
+* [s-0029.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0029.json) Test `Special:Ask` output on `mainlabel=.../?#...`, `format=table`
+* [s-0030.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases/s-0030.json) Test `Special:Concepts`
+
+-- Last updated on 2018-09-30 by `readmeContentsBuilder.php`
+
+<!-- End of generated contents by readmeContentsBuilder.php -->
+
+## Designing an integration test
+
+The `JSONScript` follows the arrange, act, assert approach, with the `setup` section containing object definitions that are planned to be used during a test. The section expects that an entity page and its contents (generally the page content in wikitext, annotations etc.) to follow a predefined structure.
+
+It is also possible to [import](https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/master/tests/phpunit/Integration/JSONScript/TestCases/p-0211.json) larger text passages or [upload files](https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/master/tests/phpunit/Integration/JSONScript/TestCases/p-0705.json) for a test scenario.
+
+When creating test scenarios, use disinct names and subjects to ensure that other tests will not interfer with the expected results. It may also be of advantage to split the setup of data (e.g. `Example/Test/1`) from the actual test subject (e.g. `Example/Test/Q.1`) to avoid conflicating comparisons or false positive results during the assertion process.
+
+<pre>
+"setup": [
+ {
+ "page": "Has text",
+ "namespace":"SMW_NS_PROPERTY",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Property:Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Example/Test/1",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has text::Some text to search]]"
+ },
+ {
+ "page": "Example/Test/Q.1",
+ "namespace":"NS_MAIN",
+ "contents": "{{#ask: [[Has text::~Some text*]] |?Has text }}"
+ }
+],
+</pre>
+
+The [bootstrap.json](https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/bootstrap.json) contains an example that can be used as starting point for a new test case.
+
+### Test assertions
+
+* The `type` provides specialized assertion methods with some of them requiring
+an extra setup to yield a comparable output but in most cases the `parser` type
+should suffice to create test assertions for common test scenarios. Available types
+are:
+ * `query`, `concept`, and `format`
+ * `parser`
+ * `parser-html`
+ * `rdf`
+ * `special`
+* The `about` describes what the test is expected to test which may help during
+ a failure to identify potential conflicts or hints on how to resolve an issue.
+* The `subject` refers to the page that was defined in the `setup` section.
+
+For example, as of version 2 the `parser` type (`ParserTestCaseProcessor`) knows
+two assertions methods:
+
+- `assert-store` is to validate data against `Store::getSemanticData`
+- `assert-output` is to validate string comparison against the `ParserOutput`
+ generated text
+
+
+#### Type `parser`
+The test result assertion provides simplified string comparison methods (mostly for
+output related assertion but expressive enough for users to understand the test
+objective and its expected results). For example, verifying that the parser
+does output a certain string, one has to the define an expected output.
+
+<pre>
+"tests": [
+ {
+ "type": "parser",
+ "about": "#0 test output of the [[ ... ]] annotation",
+ "subject": "Example/Test/1",
+ "assert-output": {
+ "to-contain": [
+ "Some text to search"
+ ],
+ "not-contain": [
+ "abc"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 test output of #ask query",
+ "subject": "Example/Test/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "Some text to search"
+ ],
+ "not-contain": [
+ "abc"
+ ]
+ }
+ }
+]
+</pre>
+
+#### Type `parser-html`
+
+To verify that the HTML code produced by the parser conforms to a certain
+structure the test type `parser-html` may be used. With this type the expected
+output structure may be specified as a CSS selector. The test will succeed if at
+least one element according to that selector is found in the output.
+
+Example:
+<pre>
+"tests": [
+ {
+ "type": "parser-html",
+ "about": "#0 Basic List format",
+ "subject": "Example/0401",
+ "assert-output": {
+ "to-contain": [
+ "p > a[ title='Bar' ] + a[ title='Baz' ] + a[ title='Foo' ] + a[ title='Quok' ]"
+ ]
+ }
+ }
+]
+</pre>
+
+For further details and limitations on the CSS selectors see the [description of
+the Symfony CssSelector
+Component](https://symfony.com/doc/current/components/css_selector.html) that is
+used for this test type.
+
+It is also possible to require an exact number of occurences of HTML elements by
+providing an array instead of just a CSS selector string.
+
+Example:
+<pre>
+ "assert-output": {
+ "to-contain": [
+ [ "p > a", 4 ]
+ ]
+ }
+</pre>
+
+Finally the general well-formedness of the HTML can be tested, although this
+will not fail for recoverable errors (see the [documentation on PHP's
+DOMDocument::loadHTML](http://php.net/manual/en/domdocument.loadhtml.php#refsect1-domdocument.loadhtml-errors)).
+
+Example:
+<pre>
+ "assert-output": {
+ "to-be-valid-html": true,
+ }
+</pre>
+
+
+### Preparing the test environment
+
+It can happen that an output is mixed with language dependent content (site vs.
+page content vs. user language) and therefore it is recommended to fix those
+settings for a test by adding something like:
+
+<pre>
+"settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+}
+</pre>
+
+By default not all settings parameter are enabled in `JsonTestCaseScriptRunner::prepareTest`
+and may require an extension in case a specific test case depends on additional
+customization.
+
+Each `json` file expects a `meta` section with:
+
+- `version` to correspond to the
+ `JsonTestCaseScriptRunner::getRequiredJsonTestCaseMinVersion` and controls the
+ JSON script definition that the runner is expected to support.
+- `is-incomplete` removes the file from the test plan if set `true`
+- `debug` as flag for support of intermediary debugging that may output internal
+ object state information.
+
+<pre>
+"meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+}
+</pre>
+
+### Define a dependency
+
+Some test scenarios may require an extension or another component and to check those dependencies before the actual test is run, use `requires` as in:
+
+<pre>
+"requires": {
+ "Maps": ">= 5.0"
+},
+</pre>
+
+### Skipping a test or mark as incomplete
+
+Sometimes certain data can cause inconsistencies with an environment hence it is
+possible to skip those cases by adding:
+
+<pre>
+{
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "page": "Example/P0413/11",
+ "contents": "[[Has date::Jan 1 300 BC]]"
+},
+</pre>
+
+<pre>
+{
+ "skip-on": {
+ "hhvm-*": "HHVM (or SQLite) shows opposite B1000, B9",
+ "mediawiki": [ ">1.30.x", "MediaWiki changed ..." ],
+ "smw": [ ">2.5.x", "SMW changed ..." ]
+ }
+}
+</pre>
+
+Constraints that include `hhvm-*` will indicate to exclude all HHVM versions while
+`>1.30.x` defines that any MW version greater than 1.30 should be ignored.
+
+It is also possible that an entire test scenario cannot be completed in a particular
+environment therefore it can be marked and skipped with:
+
+<pre>
+"meta": {
+ "skip-on": {
+ "virtuoso": "Some info as to why it is skipped.",
+ "sqlite": "...",
+ "postgres": "..."
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+}
+</pre>
+
+If a test is incomplete for some reason, use the `is-incomplete` field to indicate
+the status which henceforth avoids a test execution.
+
+### File naming
+
+The naming of a test file is arbitrary but it has been a best practice to indicate
+the type of test expected to be executed. For example, `s-0001.json` would indicate that the
+test is mostly concerned with special pages while `p-0001.json` is to handle
+parser output related assertions.
+
+### Debugging and running a test
+
+Generally, tests are run together with the `composer phpunit` execution but
+it may not always be feasible especially when trying to debug or design a new test
+case.
+
+There are two methods that can help restrict the execution during the design or
+debug phase:
+
+* Modify the `JsonTestCaseScriptRunner::getAllowedTestCaseFiles` to take an argument
+such as a file name ( e.g. `s-0014.json`) to restrict the execution of a test which
+is mostly done when running from an IDE editor
+* The command line allows to invoke a filter argument to specify a case such as
+`composer integration -- --filter 's-0014.json'`
+
+<pre>
+$ composer test -- --filter 's-0014.json'
+Using PHP 5.6.8
+
+Semantic MediaWiki: 2.5.0-alpha (SMWSQLStore3, mysql)
+MediaWiki: 1.28.0-alpha (MediaWiki vendor autoloader)
+Site language: en
+
+Execution time: 2017-01-01 12:00
+Debug logs: Enabled
+Xdebug: Disabled (or not installed)
+
+phpunit 4.8.24 by Sebastian Bergmann and contributors.
+
+Runtime: PHP 5.6.8
+Configuration: ...\extensions\SemanticMediaWiki\phpunit.xml.dist
+
+.
+
+Time: 13.02 seconds, Memory: 34.00Mb
+
+OK (1 test, 16 assertions)
+</pre>
+
+The following [video](https://youtu.be/7fDKjPFaTaY) contains a very brief introduction on how
+to run and debug a JSONScript test case. For a general introduction to the test environment,
+have a look at the following [readme](https://github.com/SemanticMediaWiki/SemanticMediaWiki/edit/master/tests/README.md).
+
+## Technical notes
+
+* The `JSON` is internally transformed into a corresponding `PHPUnit` dataset with
+the help of the `JsonTestCaseContentHandler` and `JsonTestCaseScriptRunner`.
+* A test file (e.g "myTest.json") will be loaded from the specified location in
+`JsonTestCaseScriptRunner::getTestCaseLocation` and is automatically run during
+the `PHPUnit` test execution.
+* The `readmeContentsBuilder.php` can be used to update the list of available test
+cases including its descriptions.
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/RdfTestCaseProcessor.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/RdfTestCaseProcessor.php
new file mode 100644
index 00000000..e9ced771
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/RdfTestCaseProcessor.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use SMWExportController as ExportController;
+use SMWRDFXMLSerializer as RDFXMLSerializer;
+use SMWTurtleSerializer as TurtleSerializer;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class RdfTestCaseProcessor extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var StringValidator
+ */
+ private $stringValidator;
+
+ /**
+ * @var RunnerFactory
+ */
+ private $runnerFactory;
+
+ /**
+ * @var boolean
+ */
+ private $debug = false;
+
+ /**
+ * @param Store
+ * @param StringValidator
+ */
+ public function __construct( $store, $stringValidator, $runnerFactory ) {
+ $this->store = $store;
+ $this->stringValidator = $stringValidator;
+ $this->runnerFactory = $runnerFactory;
+ }
+
+ /**
+ * @since 2.2
+ */
+ public function setDebugMode( $debugMode ) {
+ $this->debug = $debugMode;
+ }
+
+ public function process( array $case ) {
+
+ // Allows for data to be re-read from the DB instead of being fetched
+ // from the store-id-cache
+ if ( isset( $case['store']['clear-cache'] ) && $case['store']['clear-cache'] ) {
+ $this->store->clear();
+ }
+
+ if ( isset( $case['dumpRDF'] ) ) {
+ $this->assertDumpRdfOutputForCase( $case );
+ }
+
+ if ( isset( $case['exportcontroller'] ) ) {
+ $this->assertExportControllerOutputForCase( $case );
+ }
+ }
+
+ private function assertDumpRdfOutputForCase( $case ) {
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\DumpRdf' );
+ $maintenanceRunner->setQuiet();
+
+ $maintenanceRunner->setOptions( $case['dumpRDF']['parameters'] );
+ $maintenanceRunner->run();
+
+ $this->assertOutputForCase(
+ $case,
+ $maintenanceRunner->getOutput()
+ );
+ }
+
+ private function assertExportControllerOutputForCase( $case ) {
+
+ if ( isset( $case['exportcontroller']['syntax'] ) && $case['exportcontroller']['syntax'] === 'turtle' ) {
+ $serializer = new TurtleSerializer();
+ } else {
+ $serializer = new RDFXMLSerializer();
+ }
+
+ $exportController = new ExportController( $serializer );
+ $exportController->enableBacklinks( $case['exportcontroller']['parameters']['backlinks'] );
+
+ ob_start();
+
+ if ( isset( $case['exportcontroller']['print-pages'] ) ) {
+ $exportController->printPages(
+ $case['exportcontroller']['print-pages'],
+ (int)$case['exportcontroller']['parameters']['recursion'],
+ $case['exportcontroller']['parameters']['revisiondate']
+ );
+ }
+
+ if ( isset( $case['exportcontroller']['wiki-info'] ) ) {
+ $exportController->printWikiInfo();
+ }
+
+ $output = ob_get_clean();
+
+ $this->assertOutputForCase( $case, $output );
+ }
+
+ private function assertOutputForCase( $case, $output ) {
+
+ if ( $this->debug ) {
+ print_r( $output );
+ }
+
+ if ( isset( $case['assert-output']['to-contain'] ) ) {
+ $this->stringValidator->assertThatStringContains(
+ $case['assert-output']['to-contain'],
+ $output,
+ $case['about']
+ );
+ }
+
+ if ( isset( $case['assert-output']['not-contain'] ) ) {
+ $this->stringValidator->assertThatStringNotContains(
+ $case['assert-output']['not-contain'],
+ $output,
+ $case['about']
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/SpecialPageTestCaseProcessor.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/SpecialPageTestCaseProcessor.php
new file mode 100644
index 00000000..60c4e694
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/SpecialPageTestCaseProcessor.php
@@ -0,0 +1,199 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+use FauxRequest;
+use Language;
+use OutputPage;
+use RequestContext;
+use SMW\Tests\Utils\File\ContentsReader;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use SpecialPage;
+use SpecialPageFactory;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class SpecialPageTestCaseProcessor extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var StringValidator
+ */
+ private $stringValidator;
+
+ /**
+ * @var boolean
+ */
+ private $debug = false;
+
+ /**
+ * @var string
+ */
+ private $testCaseLocation = '';
+
+ /**
+ * @param Store
+ * @param StringValidator
+ */
+ public function __construct( $store, $stringValidator ) {
+ $this->store = $store;
+ $this->stringValidator = $stringValidator;
+ }
+
+ /**
+ * @since 2.4
+ */
+ public function setDebugMode( $debugMode ) {
+ $this->debug = $debugMode;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $testCaseLocation
+ */
+ public function setTestCaseLocation( $testCaseLocation ) {
+ $this->testCaseLocation = $testCaseLocation;
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param array $case
+ */
+ public function process( array $case ) {
+
+ if ( !isset( $case['special-page'] ) ) {
+ return;
+ }
+
+ if ( isset( $case['special-page']['query-parameters'] ) ) {
+ $queryParameters = $case['special-page']['query-parameters'];
+ } else {
+ $queryParameters = [];
+ }
+
+ $text = $this->getTextForRequestBy(
+ SpecialPageFactory::getPage( $case['special-page']['page'] ),
+ new FauxRequest( $case['special-page']['request-parameters'] ),
+ $queryParameters
+ );
+
+ $this->assertOutputForCase( $case, $text );
+ }
+
+ private function getTextForRequestBy( $page, $request, $queryParameters ) {
+ $response = $request->response();
+
+ $page->setContext( $this->makeRequestContext(
+ $request,
+ new MockSuperUser,
+ $this->getTitle( $page )
+ ) );
+
+ $out = $page->getOutput();
+
+ ob_start();
+ $page->execute( $queryParameters );
+
+ if ( $out->getRedirect() !== '' ) {
+ $out->output();
+ $text = ob_get_contents();
+ } elseif ( $out->isDisabled() ) {
+ $text = ob_get_contents();
+ } else {
+ $text = $out->getHTML();
+ }
+
+ ob_end_clean();
+
+ $code = $response->getStatusCode();
+
+ if ( $code > 0 ) {
+ $response->header( "Status: " . $code . ' ' . \HttpStatus::getMessage( $code ) );
+ }
+
+ return $text;
+ }
+
+ private function assertOutputForCase( $case, $text ) {
+
+ // Avoid issue with \r carriage return and \n new line
+ $text = str_replace( "\r\n", "\n", $text );
+
+ if ( isset( $case['assert-output']['to-contain'] ) ) {
+
+ if ( isset( $case['assert-output']['to-contain']['contents-file'] ) ) {
+ $contents = ContentsReader::readContentsFrom(
+ $this->testCaseLocation . $case['assert-output']['to-contain']['contents-file']
+ );
+ } else {
+ $contents = $case['assert-output']['to-contain'];
+ }
+
+ $this->stringValidator->assertThatStringContains(
+ $contents,
+ $text,
+ $case['about']
+ );
+ }
+
+ if ( isset( $case['assert-output']['not-contain'] ) ) {
+
+ if ( isset( $case['assert-output']['not-contain']['contents-file'] ) ) {
+ $contents = ContentsReader::readContentsFrom(
+ $this->testCaseLocation . $case['assert-output']['not-contain']['contents-file']
+ );
+ } else {
+ $contents = $case['assert-output']['not-contain'];
+ }
+
+ $this->stringValidator->assertThatStringNotContains(
+ $contents,
+ $text,
+ $case['about']
+ );
+ }
+ }
+
+ /**
+ * @return RequestContext
+ */
+ private function makeRequestContext( \WebRequest $request, $user, $title ) {
+
+ $context = new RequestContext();
+ $context->setRequest( $request );
+
+ $out = new OutputPage( $context );
+ $out->setTitle( $title );
+
+ $context->setOutput( $out );
+ $context->setLanguage( Language::factory( $GLOBALS['wgLanguageCode'] ) );
+
+ $user = $user === null ? new MockSuperUser() : $user;
+ $context->setUser( $user );
+
+ return $context;
+ }
+
+ /**
+ * Deprecated: Use of SpecialPage::getTitle was deprecated in MediaWiki 1.23
+ *
+ * @return Title
+ */
+ private function getTitle( SpecialPage $page ) {
+ return method_exists( $page, 'getPageTitle') ? $page->getPageTitle() : $page->getTitle();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0001.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0001.json
new file mode 100644
index 00000000..df05b93f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0001.json
@@ -0,0 +1,301 @@
+{
+ "description": "Test API `action=smwbrowse`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "API test property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "API text property",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "API page property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "API date property",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "API test concept",
+ "contents": "..."
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "API test category",
+ "contents": "..."
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0001/1",
+ "contents": "[[API text property::text 1]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0001/2",
+ "contents": "[[API text property::text 2]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0001/3",
+ "contents": "[[API page property::page 1]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0001/4",
+ "contents": "[[API page property::page 2]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0001/5",
+ "contents": "[[API date property::1 Jan 1970]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0001/6",
+ "contents": "[[API date property::2 Jan 1971]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "api",
+ "about": "#0 `smwbrowse` property search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "property",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"search\": \"API test\", \"description\": true, \"prefLabel\": true }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/a-0001.0.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#1 `smwbrowse` concept search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "concept",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"search\": \"API test\", \"description\": true, \"prefLabel\": true }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/a-0001.1.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#2 `smwbrowse` category search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "category",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"search\": \"API test\", \"description\": true, \"prefLabel\": true }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/a-0001.2.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "skip-on": {
+ "postgres": "Skipping, because I have no idea why this returning empty on Travis!",
+ "sqlite": "Skipping, because I have no idea why this returning empty on Travis!"
+ },
+ "about": "#3 `smwbrowse` page search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "page",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"search\": \"API test\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/a-0001.3.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "skip-on": {
+ "sqlite": "Skipping, because I have no idea why this returning empty during the test!"
+ },
+ "about": "#4 `smwbrowse` pvalue (text type) search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "pvalue",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"property\": \"API text property\", \"search\": \"tex\", \"sort\": \"asc\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/a-0001.4.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#5 `smwbrowse` pvalue (page type) search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "pvalue",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"property\": \"API page property\", \"search\": \"pag\", \"sort\": \"asc\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/a-0001.5.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "skip-on": {
+ "sqlite": "Skipping, because I have no idea why this is returning empty during the test!"
+ },
+ "about": "#6 `smwbrowse` pvalue (date type) search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "pvalue",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"property\": \"API date property\", \"search\": \"197\", \"sort\": \"asc\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/a-0001.6.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#7 `smwbrowse` subject lookup, JSON",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "subject",
+ "params": "{ \"subject\": \"A0001/1\" , \"ns\": 0 }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0001.7.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#8 `smwbrowse` subject lookup, HTML",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "subject",
+ "params": "{ \"subject\": \"A0001/1\" , \"ns\": 0 , \"type\": \"html\", \"options\": {} }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0001.8.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#9 `smwbrowse` (distinct value, empty search) psubject search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "psubject",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"property\": \"API page property\", \"value\": \"Page 1\", \"sort\": \"asc\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0001.9.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#10 `smwbrowse` (empty value, empty search) psubject search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "psubject",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"property\": \"API page property\", \"value\": \"\", \"sort\": \"asc\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0001.10.txt"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#11 `smwbrowse` (empty value, distinct search) psubject search",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "psubject",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"property\": \"API page property\", \"value\": \"\", \"search\": \"/4\", \"sort\": \"asc\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0001.11.txt"
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgCacheUsage": {
+ "api.browse": false,
+ "api.browse.pvalue": false,
+ "api.browse.psubject": false
+ },
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "SMW_NS_CONCEPT": true,
+ "NS_CATEGORY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0002.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0002.json
new file mode 100644
index 00000000..f8de5b1a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0002.json
@@ -0,0 +1,106 @@
+{
+ "description": "Test API `action=ask` and `action=askargs` with `api_version` 2 + 3",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "API test page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "API test text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/A0002/1",
+ "contents": "[[API test page::123]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "api",
+ "about": "#0 `ask` version 2",
+ "api": {
+ "parameters": {
+ "action": "ask",
+ "format": "json",
+ "query": "[[API test page::123]] |?API test page",
+ "api_version": "2"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0002.0.json"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#1 `ask` version 3",
+ "api": {
+ "parameters": {
+ "action": "ask",
+ "format": "json",
+ "query": "[[API test page::123]] |?API test page",
+ "api_version": "3"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0002.1.json"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#2 `askargs` version 2",
+ "api": {
+ "parameters": {
+ "action": "askargs",
+ "format": "json",
+ "conditions": "API test page::123",
+ "printouts": "API test page",
+ "api_version": "2"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0002.2.json"
+ }
+ }
+ },
+ {
+ "type": "api",
+ "about": "#3 `askargs` version 3",
+ "api": {
+ "parameters": {
+ "action": "askargs",
+ "format": "json",
+ "conditions": "API test page::123",
+ "printouts": "API test page",
+ "api_version": "3"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.a-0002.3.json"
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "SMW_NS_CONCEPT": true,
+ "NS_CATEGORY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0003.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0003.json
new file mode 100644
index 00000000..f74e5121
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/a-0003.json
@@ -0,0 +1,71 @@
+{
+ "description": "Test API `action=smwbrowse`, `browse=pvalue`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text extra",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0003/1",
+ "contents": "[[Has text::123]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0003/2",
+ "contents": "[[Has text::1234]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "A0003/3",
+ "contents": "[[Has text extra::12345]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "api",
+ "about": "#0 `smwbrowse` pvalue (text type) search, abide or/and on property",
+ "api": {
+ "parameters": {
+ "action": "smwbrowse",
+ "format": "json",
+ "browse": "pvalue",
+ "params": "{ \"limit\": 10, \"offset\": 0, \"property\": \"Has text\", \"search\": \"123\", \"sort\": \"asc\" }"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "123",
+ "1234"
+ ],
+ "not-contain": [
+ "12345"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgCacheUsage": {
+ "api.browse.pvalue": false
+ },
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "SMW_NS_CONCEPT": true,
+ "NS_CATEGORY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0001.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0001.json
new file mode 100644
index 00000000..ee95c0a5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0001.json
@@ -0,0 +1,108 @@
+{
+ "description": "Test `format=debug` output",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]] [[Display precision of::2]]"
+ },
+ {
+ "page": "Example/0001",
+ "contents": "[[Has page::Foo]] [[Has text::bar]]"
+ },
+ {
+ "page": "Example/F0001/2",
+ "contents": "[[Has number::3.555567]]"
+ },
+ {
+ "page": "Example/0001/1",
+ "contents": "{{#ask:[[Has page::Foo]] [[Has page::42]] |?Has page |?Has text |format=debug }}"
+ },
+ {
+ "page": "Example/F0001/Q.1",
+ "contents": "{{#ask: [[Has number::3.555567]] |?Has number |format=debug }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 simple debug output",
+ "subject": "Example/0001/1",
+ "skip-on": {
+ "elastic": "Different debug format"
+ },
+ "assert-output": {
+ "to-contain": [
+ "&#91;&#91;Has page::Foo]] &#91;&#91;Has page::42]]",
+ "Query-Size:4",
+ "Query-Depth:1",
+ "None"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#0.elastic simple debug output",
+ "subject": "Example/0001/1",
+ "skip-on": {
+ "elastic": [ "not", "Different debug format" ]
+ },
+ "assert-output": {
+ "to-contain": [
+ "&#91;&#91;Has page::Foo]] &#91;&#91;Has page::42]]",
+ "\"query size\": 4",
+ "\"query depth\": 1"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 value input/output not be constraint by precision",
+ "subject": "Example/F0001/Q.1",
+ "skip-on": {
+ "elastic": "Different debug format"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smwpre\">&#91;&#91;Has number::3.555567]]</div>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1.elastic value input/output not be constraint by precision",
+ "subject": "Example/F0001/Q.1",
+ "skip-on": {
+ "elastic": [ "not", "Different debug format" ]
+ },
+ "assert-output": {
+ "to-contain": [
+ "\"query\": \"&#91;&#91;Has number::3.555567]]\""
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0101.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0101.json
new file mode 100644
index 00000000..e490bf17
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0101.json
@@ -0,0 +1,125 @@
+{
+ "description": "Test `format=template` output using unnamed arguments (#885)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateOutputUsingUnnamedArgumentsForNonUnicode",
+ "contents": "<includeonly>[{{{#}}}]:{{{1}}}:{{{2}}}:{{{#userparam}}}:</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateOutputUsingUnnamedArgumentsForNonUnicodeExtra",
+ "contents": "<includeonly><div>{{{#userparam}}}</div></includeonly>"
+ },
+ {
+ "page": "Foo",
+ "contents": "[[Has page property::ABC]] [[Has page property::DEF]] [[Category:template-001]]"
+ },
+ {
+ "page": "Bar",
+ "contents": "[[Has page property::ABC]] [[Has page property::DEF]] [[Category:template-001]]"
+ },
+ {
+ "page": "123",
+ "contents": "[[Has page property::ABC]] [[Has page property::DEF]] [[Category:template-001]]"
+ },
+ {
+ "page": "yxz",
+ "contents": "[[Has page property::ABC]] [[Has page property::DEF]] [[Category:template-001]]"
+ },
+ {
+ "page": "template-001-asc-order-unnamed-args",
+ "contents": "{{#ask:[[Category:template-001]][[Has page property::ABC]] |?Has page property |sep=, |format=template |order=asc |link=none |limit=3 |searchlabel=furtherresults |userparam=[$%&*==42] |template=TemplateOutputUsingUnnamedArgumentsForNonUnicode |introtemplate=TemplateOutputUsingUnnamedArgumentsForNonUnicodeExtra |outrotemplate=TemplateOutputUsingUnnamedArgumentsForNonUnicodeExtra}}"
+ },
+ {
+ "page": "template-001-desc-order-unnamed-args",
+ "contents": "{{#ask:[[Category:template-001]][[Has page property::ABC]] |?Has page property |sep=, |format=template |order=desc |link=none |limit=3 |searchlabel=furtherresults |userparam=[$%&*==42] |template=TemplateOutputUsingUnnamedArgumentsForNonUnicode |introtemplate=TemplateOutputUsingUnnamedArgumentsForNonUnicodeExtra |outrotemplate=TemplateOutputUsingUnnamedArgumentsForNonUnicodeExtra}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 (1.31-) asc template output using unnamed arguments, #885 further results link",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "template-001-asc-order-unnamed-args",
+ "assert-output": {
+ "to-contain": [
+ "<div>[$%&amp;*==42]</div>",
+ "[0]:123:ABC, DEF:[$%&amp;*==42]:",
+ "[1]:Bar:ABC, DEF:[$%&amp;*==42]:",
+ "[2]:Foo:ABC, DEF:[$%&amp;*==42]:",
+ "<div>[$%&amp;*==42]</div><span class=\"smw-template-furtherresults\">"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#0 (1.31+) asc template output using unnamed arguments, #885 further results link",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "template-001-asc-order-unnamed-args",
+ "assert-output": {
+ "to-contain": [
+ "<div>[$%&amp;*==42]</div>",
+ "[0]:123:ABC, DEF:[$%&amp;*==42]:",
+ "[1]:Bar:ABC, DEF:[$%&amp;*==42]:",
+ "[2]:Foo:ABC, DEF:[$%&amp;*==42]:",
+ "<div>[$%&amp;*==42]</div><p><span class=\"smw-template-furtherresults\">"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (1.31-) desc template output using unnamed arguments",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "template-001-desc-order-unnamed-args",
+ "assert-output": {
+ "to-contain": [
+ "<div>[$%&amp;*==42]</div>",
+ "[0]:Yxz:ABC, DEF:[$%&amp;*==42]:",
+ "[1]:Foo:ABC, DEF:[$%&amp;*==42]:",
+ "[2]:Bar:ABC, DEF:[$%&amp;*==42]:",
+ "<div>[$%&amp;*==42]</div><span class=\"smw-template-furtherresults\">"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (1.31+) desc template output using unnamed arguments",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "template-001-desc-order-unnamed-args",
+ "assert-output": {
+ "to-contain": [
+ "<div>[$%&amp;*==42]</div>",
+ "[0]:Yxz:ABC, DEF:[$%&amp;*==42]:",
+ "[1]:Foo:ABC, DEF:[$%&amp;*==42]:",
+ "[2]:Bar:ABC, DEF:[$%&amp;*==42]:",
+ "<div>[$%&amp;*==42]</div><p><span class=\"smw-template-furtherresults\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0102.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0102.json
new file mode 100644
index 00000000..7e7dd0d2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0102.json
@@ -0,0 +1,81 @@
+{
+ "description": "Test `format=template` output + unicode characters (#988, skip postgres)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateOutputUsingNamedArgumentsForUnicodeIncludedSubject",
+ "contents": "<includeonly>[{{{#}}}]:{{{1}}}:{{{Has page property}}}:{{{#userparam}}}:</includeonly>"
+ },
+ {
+ "page": "Foo",
+ "contents": "[[Has page property::一二三]] [[Has page property::456]] [[Category:template-002]]"
+ },
+ {
+ "page": "Bar",
+ "contents": "[[Has page property::一二三]] [[Has page property::456]] [[Category:template-002]]"
+ },
+ {
+ "page": "123",
+ "contents": "[[Has page property::一二三]] [[Has page property::456]] [[Category:template-002]]"
+ },
+ {
+ "page": "テスト",
+ "contents": "[[Has page property::一二三]] [[Has page property::456]] [[Category:template-002]]"
+ },
+ {
+ "page": "template-002-asc-order-named-args",
+ "contents": "{{#ask:[[Category:template-002]]<q>[[Has page property:一二三]] OR [[Has page property::456]]</q> |?Has page property |format=template |order=asc |sep=; |valuesep=; <nowiki/>|link=none |limit=10 |userparam=[$%&*==42] |template=TemplateOutputUsingNamedArgumentsForUnicodeIncludedSubject ||named args=yes}}"
+ },
+ {
+ "page": "template-002-desc-order-named-args",
+ "contents": "{{#ask:[[Category:template-002]]<q>[[Has page property:一二三]] OR [[Has page property::456]]</q> |?Has page property |format=template |order=desc |sep=; |valuesep=; <nowiki/>|link=none |limit=10 |userparam=[$%&*==42] |template=TemplateOutputUsingNamedArgumentsForUnicodeIncludedSubject ||named args=yes}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 asc output order, without further links",
+ "subject": "template-002-asc-order-named-args",
+ "assert-output": {
+ "to-contain": [
+ "[0]:123:一二三; 456:[$%&amp;*==42]:",
+ "[1]:Bar:一二三; 456:[$%&amp;*==42]:",
+ "[2]:Foo:一二三; 456:[$%&amp;*==42]:",
+ "[3]:テスト:一二三; 456:[$%&amp;*==42]:"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 desc output order, without further links",
+ "subject": "template-002-desc-order-named-args",
+ "assert-output": {
+ "to-contain": [
+ "[0]:テスト:一二三; 456:[$%&amp;*==42]:",
+ "[1]:Foo:一二三; 456:[$%&amp;*==42]:",
+ "[2]:Bar:一二三; 456:[$%&amp;*==42]:",
+ "[3]:123:一二三; 456:[$%&amp;*==42]:"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "Unicode needs special treatment in postgres"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0103.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0103.json
new file mode 100644
index 00000000..53964aad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0103.json
@@ -0,0 +1,124 @@
+{
+ "description": "Test `format=template` with self reference (#988, guard against template self-reference in ask/show query)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has blob property",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Page with annotation for template usage",
+ "contents": "[[Has blob property::Template one]] [[Has page property::Template two]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateWithReferenceToItself",
+ "contents": "<includeonly>{{#ask: [[Has page property::Template two]] OR [[Has page property::Template three]]|format=template|template=TemplateWithReferenceToItself}}</includeonly>"
+ },
+ {
+ "page": "PageContainsAskWithTemplateUsage",
+ "contents": "{{#ask: [[Has blob property::Template one]]|format=template|template=TemplateWithReferenceToItself|import-annotation=true}}"
+ },
+ {
+ "page": "PageContainsTemplateTransclusion",
+ "contents": "[[Has page property::Template three]] {{TemplateWithReferenceToItself}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 query profile (use invert query)",
+ "condition": "[[-Has query::PageContainsAskWithTemplateUsage]]",
+ "printouts": [
+ "Query size",
+ "Query string",
+ "Query depth"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "PageContainsAskWithTemplateUsage#0##_QUERY243ffe4b18342e8ae68152cedc5b1966",
+ "PageContainsAskWithTemplateUsage#0##_QUERYe295f9adeb904a1cbab1e30eb56d79ba"
+ ],
+ "count": "2",
+ "datavalues": [
+ {
+ "property": "Query size",
+ "value": "1"
+ },
+ {
+ "property": "Query depth",
+ "value": "1"
+ },
+ {
+ "property": "Query string",
+ "value": "[[Has blob property::Template one]]"
+ },
+ {
+ "property": "Query size",
+ "value": "4"
+ },
+ {
+ "property": "Query depth",
+ "value": "1"
+ },
+ {
+ "property": "Query string",
+ "value": " <q> <q>[[Has page property::Template two]]</q> OR <q>[[Has page property::Template three]]</q> </q> "
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 query profile on page/template transcluded page (use invert query)",
+ "condition": "[[-Has query::PageContainsTemplateTransclusion]]",
+ "printouts": [
+ "Query size",
+ "Query string",
+ "Query depth"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "PageContainsTemplateTransclusion#0##_QUERY243ffe4b18342e8ae68152cedc5b1966"
+ ],
+ "count": "1",
+ "datavalues": [
+ {
+ "property": "Query size",
+ "value": "4"
+ },
+ {
+ "property": "Query depth",
+ "value": "1"
+ },
+ {
+ "property": "Query string",
+ "value": " <q> <q>[[Has page property::Template two]]</q> OR <q>[[Has page property::Template three]]</q> </q> "
+ }
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0104.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0104.json
new file mode 100644
index 00000000..8323d1ef
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0104.json
@@ -0,0 +1,159 @@
+{
+ "description": "Test `format=list, ul, ol, template` (#2022,`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateOutputUsingNamedArguments",
+ "contents": "<includeonly>{{{Has page}}}:{{{Has text}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateOutputUsingNamedArguments-intro",
+ "contents": "<includeonly>(I)</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateOutputUsingNamedArguments-outro",
+ "contents": "<includeonly>(O)</includeonly>"
+ },
+ {
+ "page": "Example/F0104/1",
+ "contents": "[[Has page::{{PAGENAME}}]] [[Has text::123]] [[Has text::456]] [[Category:F0104]]"
+ },
+ {
+ "page": "Example/F0104/2",
+ "contents": "[[Has page::{{PAGENAME}}]] [[Has text::abc]] [[Has text::def]] [[Category:F0104]]"
+ },
+ {
+ "page": "Example/F0104/3",
+ "contents": "[[Has page::{{PAGENAME}}]] [[Has text::001]] [[Has text::0011]] [[Category:F0104]]"
+ },
+ {
+ "page": "Example/F0104/Q.1",
+ "contents": "{{#ask: [[Category:F0104]] |?Has page |?Has text |format=list |link=none |headers=plain }}"
+ },
+ {
+ "page": "Example/F0104/Q.2",
+ "contents": "{{#ask: [[Category:F0104]] |?Has page |?Has text |format=list |link=none |headers=plain |sep=;}}"
+ },
+ {
+ "page": "Example/F0104/Q.3",
+ "contents": "{{#ask: [[Category:F0104]] |?Has page |?Has text |format=list |link=none |headers=plain |sep=;_}}"
+ },
+ {
+ "page": "Example/F0104/Q.4",
+ "contents": "{{#ask: [[Category:F0104]] |?Has page |?Has text |format=ul |link=none |headers=plain }}"
+ },
+ {
+ "page": "Example/F0104/Q.5",
+ "contents": "{{#ask: [[Category:F0104]] |?Has page |?Has text |format=ul |link=none |headers=plain |propsep=; }}"
+ },
+ {
+ "page": "Example/F0104/Q.6",
+ "contents": "{{#ask: [[Category:F0104]] |?Has page |?Has text |format=template |named args=yes |introtemplate=TemplateOutputUsingNamedArguments-intro |template=TemplateOutputUsingNamedArguments |outrotemplate=TemplateOutputUsingNamedArguments-outro |link=none |headers=plain }}"
+ },
+ {
+ "page": "Example/F0104/Q.7",
+ "contents": "{{#ask: [[Category:F0104]] |?Has page |?Has text |sep=, |valuesep=; |format=template |named args=yes |introtemplate=TemplateOutputUsingNamedArguments-intro |template=TemplateOutputUsingNamedArguments |outrotemplate=TemplateOutputUsingNamedArguments-outro |link=none |headers=plain }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 (list, no sep)",
+ "subject": "Example/F0104/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-format list-format\"><span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/1</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/1</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">123</span>, <span class=\"smw-value\">456</span></span>)</span>, <span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/2</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/2</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">abc</span>, <span class=\"smw-value\">def</span></span>)</span>, <span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/3</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/3</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">001</span>, <span class=\"smw-value\">0011</span></span>)</span></span>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (list, sep=;)",
+ "subject": "Example/F0104/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-format list-format\"><span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/1</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/1</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">123</span>, <span class=\"smw-value\">456</span></span>)</span>;<span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/2</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/2</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">abc</span>, <span class=\"smw-value\">def</span></span>)</span>;<span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/3</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/3</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">001</span>, <span class=\"smw-value\">0011</span></span>)</span></span>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 (list, sep=;_)",
+ "subject": "Example/F0104/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<p><span class=\"smw-format list-format\"><span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/1</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/1</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">123</span>, <span class=\"smw-value\">456</span></span>)</span>;_<span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/2</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/2</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">abc</span>, <span class=\"smw-value\">def</span></span>)</span>;_<span class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/3</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/3</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">001</span>, <span class=\"smw-value\">0011</span></span>)</span></span>\n</p>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 (ul, no sep)",
+ "subject": "Example/F0104/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/1</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/1</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">123</span>, <span class=\"smw-value\">456</span></span>)</li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/2</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/2</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">abc</span>, <span class=\"smw-value\">def</span></span>)</li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/3</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/3</span></span>, <span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">001</span>, <span class=\"smw-value\">0011</span></span>)</li>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 (ul, propsep=;)",
+ "subject": "Example/F0104/Q.5",
+ "assert-output": {
+ "to-contain": [
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/1</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/1</span></span>;<span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">123</span>, <span class=\"smw-value\">456</span></span>)</li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/2</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/2</span></span>;<span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">abc</span>, <span class=\"smw-value\">def</span></span>)</li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Example/F0104/3</span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has page</span>: <span class=\"smw-value\">Example/F0104/3</span></span>;<span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">001</span>, <span class=\"smw-value\">0011</span></span>)</li>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 (template, no sep)",
+ "subject": "Example/F0104/Q.6",
+ "assert-output": {
+ "to-contain": [
+ "(I)Example/F0104/1:123, 456Example/F0104/2:abc, defExample/F0104/3:001, 0011(O)"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#6 (template, sep=;)",
+ "subject": "Example/F0104/Q.7",
+ "assert-output": {
+ "to-contain": [
+ "(I)Example/F0104/1:123;456,Example/F0104/2:abc;def,Example/F0104/3:001;0011(O)"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0105.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0105.json
new file mode 100644
index 00000000..d45d24fc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0105.json
@@ -0,0 +1,125 @@
+{
+ "description": "Test `format=list, ul, ol` on `_qty` property (`wgContLang=en`, `SMW_DV_NUMV_USPACE`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area",
+ "contents": "[[Has type::Quantity]], [[Corresponds to::1 km², km ²]] [[Corresponds to::0.38610 sq mi, sqmi]] [[Corresponds to::1000 m², m ²]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/F0105/1",
+ "contents": "[[Has area::10 km ²]] [[Category:F0105]]"
+ },
+ {
+ "page": "Example/F0105/2",
+ "contents": "[[Has text::Test <li>Item</li>]] [[Category:F0105]]"
+ },
+ {
+ "page": "Example/F0105/Q.1.1",
+ "contents": "{{#ask: [[Category:F0105]] [[Has area::+]] |?Has area |format=list |headers=plain }}"
+ },
+ {
+ "page": "Example/F0105/Q.1.2",
+ "contents": "{{#ask: [[Category:F0105]] [[Has area::+]] |?Has area |format=ul |headers=plain }}"
+ },
+ {
+ "page": "Example/F0105/Q.1.3",
+ "contents": "{{#ask: [[Category:F0105]] [[Has area::+]] |?Has area |format=ol |headers=plain }}"
+ },
+ {
+ "page": "Example/F0105/Q.2.1",
+ "contents": "{{#ask: [[Category:F0105]] [[Has text::+]] |?Has text |format=list |headers=plain }}"
+ },
+ {
+ "page": "Example/F0105/Q.2.2",
+ "contents": "{{#ask: [[Category:F0105]] [[Has text::+]] |?Has text |format=ul |headers=plain }}"
+ },
+ {
+ "page": "Example/F0105/Q.2.3",
+ "contents": "{{#ask: [[Category:F0105]] [[Has text::+]] |?Has text |format=ol |headers=plain }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 (format=list)",
+ "subject": "Example/F0105/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"3.861 sq mi 10,000 m²\"><span class=\"smwtext\">10&#160;km²</span><span class=\"smwttcontent\">3.861&#160;sq mi <br />10,000&#160;m² <br /></span>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (format=ul)",
+ "subject": "Example/F0105/Q.1.2",
+ "assert-output": {
+ "to-contain": [
+ "title=\"3.861 sq mi 10,000 m²\"><span class=\"smwtext\">10&#160;km²</span><span class=\"smwttcontent\">3.861&#160;sq mi <br />10,000&#160;m² <br /></span>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 (format=ol)",
+ "subject": "Example/F0105/Q.1.3",
+ "assert-output": {
+ "to-contain": [
+ "title=\"3.861 sq mi 10,000 m²\"><span class=\"smwtext\">10&#160;km²</span><span class=\"smwttcontent\">3.861&#160;sq mi <br />10,000&#160;m² <br /></span>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 (format=list) with <li> element",
+ "subject": "Example/F0105/Q.2.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/F0105/2\">Example/F0105/2</a></span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">Test <li>Item</li></span></span>)"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 (format=ul) with sanitized <li> element",
+ "subject": "Example/F0105/Q.2.2",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/F0105/2\">Example/F0105/2</a></span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">Test &lt;li&gt;Item&lt;/li&gt;</span></span>)</li>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 (format=ol) with sanitized <li> element",
+ "subject": "Example/F0105/Q.2.3",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/F0105/2\">Example/F0105/2</a></span></span> (<span class=\"smw-field\"><span class=\"smw-field-label\">Has text</span>: <span class=\"smw-value\">Test &lt;li&gt;Item&lt;/li&gt;</span></span>)</li>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDVFeatures": [
+ "SMW_DV_NUMV_USPACE"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0201.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0201.json
new file mode 100644
index 00000000..9b7f90b0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0201.json
@@ -0,0 +1,178 @@
+{
+ "description": "Test `format=table` on boolean table output formatting (#896, #1464)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has success state",
+ "contents": "[[Has type::Boolean]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has boolean",
+ "contents": "[[Has type::Boolean]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project name",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Project one",
+ "contents": "[[Category:BoolProjects]] [[Has success state::true]] [[Has project name::One]]"
+ },
+ {
+ "page": "Project two",
+ "contents": "[[Category:BoolProjects]] [[Has success state::false]] [[Has project name::Two]]"
+ },
+ {
+ "page": "Example/F0201/1",
+ "contents": "{{#ask: [[Category:BoolProjects]]|?Has success state#x|?Has project name|limit=10|format=table |link=none|headers=plain}}"
+ },
+ {
+ "page": "BooleanTable-ToLabelBoolValue",
+ "contents": "{{#ask: [[Category:BoolProjects]]|?Has success state#success,failure|limit=10|format=table}}"
+ },
+ {
+ "page": "BooleanTable-ToLabelBoolValueAndColumn",
+ "contents": "{{#ask: [[Category:BoolProjects]]|?Has success state#success,failure=Status|limit=10|format=table}}"
+ },
+ {
+ "page": "Example/F0201/3",
+ "contents": "{{#subobject: |Has boolean=true |@category=F0201 }}{{#subobject: |Has boolean=false |@category=F0201 }}"
+ },
+ {
+ "page": "Example/F0201/3a",
+ "contents": "{{#ask: [[Category:F0201]] |?Has boolean#✓,✕ }}"
+ },
+ {
+ "page": "Example/F0201/3b",
+ "contents": "{{#ask: [[Category:F0201]] |?Has boolean#○,× }}"
+ },
+ {
+ "page": "Example/F0201/3c",
+ "contents": "{{#ask: [[Category:F0201]] |?Has boolean#<span style=\"color: green; font-size: 120%;\">&#10003;</span>,<span style=\"color: #AA0000; font-size: 120%;\">&#10005;</span>=Label on (&#10003;,&#10005;) }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 Check format#x output, see #896",
+ "subject": "Example/F0201/1",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Project one</td><td class=\"Has-success-state smwtype_boo\" data-sort-value=\"1\"><span style=\"font-family: sans-serif;\">X</span></td><td class=\"Has-project-name smwtype_txt\">One</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Project two</td><td class=\"Has-success-state smwtype_boo\" data-sort-value=\"0\">&#160;</td><td class=\"Has-project-name smwtype_txt\">Two</td></tr>",
+ "</table>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (1.31-) Check bool label output value label",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "BooleanTable-ToLabelBoolValue",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "title=\"Property:Has success state\">Has success state</a></th><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">",
+ "title=\"Project one\">Project one</a></td><td class=\"Has-success-state smwtype_boo\" data-sort-value=\"1\">success</td>",
+ "title=\"Project two\">Project two</a></td><td class=\"Has-success-state smwtype_boo\" data-sort-value=\"0\">failure</td>",
+ "</table>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (1.31+) Check bool label output value label",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "BooleanTable-ToLabelBoolValue",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "title=\"Property:Has success state\">Has success state</a></th></tr><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">",
+ "title=\"Project one\">Project one</a></td><td class=\"Has-success-state smwtype_boo\" data-sort-value=\"1\">success</td>",
+ "title=\"Project two\">Project two</a></td><td class=\"Has-success-state smwtype_boo\" data-sort-value=\"0\">failure</td>",
+ "</table>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 (1.31-) Check bool/column label output",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "BooleanTable-ToLabelBoolValueAndColumn",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "title=\"Property:Has success state\">Status</a></th><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">",
+ "title=\"Project one\">Project one</a></td><td class=\"Status smwtype_boo\" data-sort-value=\"1\">success</td>",
+ "title=\"Project two\">Project two</a></td><td class=\"Status smwtype_boo\" data-sort-value=\"0\">failure</td>",
+ "</table>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 (1.31+) Check bool/column label output",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "BooleanTable-ToLabelBoolValueAndColumn",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "title=\"Property:Has success state\">Status</a></th></tr><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">",
+ "title=\"Project one\">Project one</a></td><td class=\"Status smwtype_boo\" data-sort-value=\"1\">success</td>",
+ "title=\"Project two\">Project two</a></td><td class=\"Status smwtype_boo\" data-sort-value=\"0\">failure</td>",
+ "</table>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3",
+ "subject": "Example/F0201/3a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"1\">✓</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"0\">✕</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4",
+ "subject": "Example/F0201/3b",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"1\">â—‹</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"0\">×</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 (#1464)",
+ "subject": "Example/F0201/3c",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Label-on-(&amp;#10003;,&amp;#10005;) smwtype_boo\" data-sort-value=\"1\"><span style=\"color: green; font-size: 120%;\">&#10003;</span></td>",
+ "<td class=\"Label-on-(&amp;#10003;,&amp;#10005;) smwtype_boo\" data-sort-value=\"0\"><span style=\"color: #AA0000; font-size: 120%;\">&#10005;</span></td>"
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0202.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0202.json
new file mode 100644
index 00000000..6216018f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0202.json
@@ -0,0 +1,94 @@
+{
+ "description": "Test `format=table` with sep cell formatting, #495 (`wgContLang=en`,`wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Table-page",
+ "contents": "[[Has page::Foo]] [[Has page::42]] [[Has text::bar]] [[Has text::1001]]"
+ },
+ {
+ "page": "Table-without-sep-parameter",
+ "contents": "{{#ask:[[Has page::Foo]] [[Has page::42]]\n |?Has page\n |?Has text\n |format=table\n |headers=plain\n |link=none\n }}"
+ },
+ {
+ "page": "Table-with-sep-parameter",
+ "contents": "{{#ask:[[Has page::Foo]] [[Has page::42]]\n |?Has page\n |?Has text\n |format=table\n |sep=;\n |headers=plain\n |link=none\n }}"
+ },
+ {
+ "page": "Broadtable-with-sep-parameter",
+ "contents": "{{#ask:[[Has page::Foo]] [[Has page::42]]\n |?Has page\n |?Has text\n |format=broadtable\n |sep=;\n |headers=plain\n |link=none\n }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 table without sep",
+ "subject": "Table-without-sep-parameter",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<th>&#160;</th><th class=\"Has-page\">Has page</th>",
+ "<th class=\"Has-text\">Has text</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Table-page</td>",
+ "<td class=\"Has-page smwtype_wpg\">Foo<br />42</td>",
+ "<td class=\"Has-text smwtype_txt\">bar<br />1001</td></tr>",
+ "</table>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 table with sep",
+ "subject": "Table-with-sep-parameter",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<th>&#160;</th><th class=\"Has-page\">Has page</th>",
+ "<th class=\"Has-text\">Has text</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Table-page</td>",
+ "<td class=\"Has-page smwtype_wpg\">Foo;42</td>",
+ "<td class=\"Has-text smwtype_txt\">bar;1001</td></tr>",
+ "</table>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 broadtable with sep",
+ "subject": "Broadtable-with-sep-parameter",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable broadtable\" width=\"100%\">",
+ "<th>&#160;</th><th class=\"Has-page\">Has page</th>",
+ "<th class=\"Has-text\">Has text</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Table-page</td>",
+ "<td class=\"Has-page smwtype_wpg\">Foo;42</td>",
+ "<td class=\"Has-text smwtype_txt\">bar;1001</td></tr>",
+ "</table>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0203.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0203.json
new file mode 100644
index 00000000..2e1ba511
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0203.json
@@ -0,0 +1,78 @@
+{
+ "description": "Test `format=table` to sort by category (#1286)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/F0303/A",
+ "contents": "[[Has project::Project A]] [[Category:Project group A]]"
+ },
+ {
+ "page": "Example/F0303/AA",
+ "contents": "[[Has project::Project AA]] [[Category:Project group A]]"
+ },
+ {
+ "page": "Example/F0303/B",
+ "contents": "[[Has project::Project B]] [[Category:Project group B]]"
+ },
+ {
+ "page": "Example/F0303/C",
+ "contents": "[[Has project::Project C]] [[Category:Project group C]]"
+ },
+ {
+ "page": "Example/F0303/ASC",
+ "contents": "{{#ask: [[Has project::~Project*]] |?Has project |?Category |sort=Category,Has project |order=asc,asc |link=none |format=table}}"
+ },
+ {
+ "page": "Example/F0303/DESC",
+ "contents": "{{#ask: [[Has project::~Project*]] |?Has project |?Category |sort=Category,Has project |order=desc,asc |link=none |format=table}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 asc order",
+ "subject": "Example/F0303/ASC",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/F0303/A</td><td class=\"Has-project smwtype_wpg\">Project A</td><td class=\"Category smwtype_wpg\">Category:Project group A</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/F0303/AA</td><td class=\"Has-project smwtype_wpg\">Project AA</td><td class=\"Category smwtype_wpg\">Category:Project group A</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/F0303/B</td><td class=\"Has-project smwtype_wpg\">Project B</td><td class=\"Category smwtype_wpg\">Category:Project group B</td></tr>",
+ "<tr data-row-number=\"4\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/F0303/C</td><td class=\"Has-project smwtype_wpg\">Project C</td><td class=\"Category smwtype_wpg\">Category:Project group C</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 desc order",
+ "subject": "Example/F0303/DESC",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/F0303/C</td><td class=\"Has-project smwtype_wpg\">Project C</td><td class=\"Category smwtype_wpg\">Category:Project group C</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/F0303/B</td><td class=\"Has-project smwtype_wpg\">Project B</td><td class=\"Category smwtype_wpg\">Category:Project group B</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/F0303/A</td><td class=\"Has-project smwtype_wpg\">Project A</td><td class=\"Category smwtype_wpg\">Category:Project group A</td></tr>",
+ "<tr data-row-number=\"4\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/F0303/AA</td><td class=\"Has-project smwtype_wpg\">Project AA</td><td class=\"Category smwtype_wpg\">Category:Project group A</td></tr>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0204.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0204.json
new file mode 100644
index 00000000..6836cedd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0204.json
@@ -0,0 +1,52 @@
+{
+ "description": "Test `format=table` on `_qty` for different positional unit preference (#1329, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Currency",
+ "contents": "[[Has type::Quantity]], [[Display units::€,£,¥]] [[Corresponds to::€ 1]] [[Corresponds to::1.06 US, US$, $]] [[Corresponds to::0.70 British Pound,GBP,£]] [[Corresponds to::¥,JPY,Japanese Yen 114.2121]]"
+ },
+ {
+ "page": "Example/F0204/1",
+ "contents": "[[Currency::12 €]] [[Currency::¥ 500]] [[Currency::2 £]]"
+ },
+ {
+ "page": "Example/F0204/2",
+ "contents": "[[Currency::€ 20]] [[Currency::2000 JPY]] [[Currency::0.5 GBP]]"
+ },
+ {
+ "page": "Example/F0204/3",
+ "contents": "{{#ask: [[Currency::+]] |?Currency |format=table |headers=plain }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 output with different positional preference",
+ "subject": "Example/F0204/3",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwtext\">€&#160;12</span><span class=\"smwttcontent\">8.4&#160;£ <br />¥&#160;1,370.545 <br /></span></span>",
+ "<span class=\"smwtext\">€&#160;4.378</span><span class=\"smwttcontent\">3.064&#160;£ <br />¥&#160;500 <br /></span></span>",
+ "<span class=\"smwtext\">€&#160;2.857</span><span class=\"smwttcontent\">2&#160;£ <br />¥&#160;326.32 <br /></span></span>",
+ "<span class=\"smwtext\">€&#160;20</span><span class=\"smwttcontent\">14&#160;£ <br />¥&#160;2,284.242 <br /></span></span>",
+ "<span class=\"smwtext\">€&#160;17.511</span><span class=\"smwttcontent\">12.258&#160;£ <br />¥&#160;2,000 <br /></span></span>",
+ "<span class=\"smwtext\">€&#160;0.714</span><span class=\"smwttcontent\">0.5&#160;£ <br />¥&#160;81.58 <br /></span></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0205.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0205.json
new file mode 100644
index 00000000..e53123c1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0205.json
@@ -0,0 +1,93 @@
+{
+ "description": "Test `format=table` on `|+align=`/`|+limit`/`|+order`/`|+width=` extra printout parameters (T18571, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Example/F0205/1/1",
+ "contents": "[[Has number::1]] [[Has number::42]] [[Has number::.02]]"
+ },
+ {
+ "page": "Example/F0205/1/2",
+ "contents": "[[Has number::21]] [[Has number::1001]] [[Has number::2.02]]"
+ },
+ {
+ "page": "Example/F0205/1a",
+ "contents": "{{#ask: [[~Example/F0205/1/*]] |?Has number |+align=right |+limit=2 |+order=asc |format=table |headers=plain }}"
+ },
+ {
+ "page": "Example/F0205/1b",
+ "contents": "{{#ask: [[~Example/F0205/1/*]] |?Has number |+align=left |+limit=2 |+order=desc |format=table |headers=plain }}"
+ },
+ {
+ "page": "Example/F0205/Q.2",
+ "contents": "{{#ask: [[~Example/F0205/1/*]] |?Has number |+width=50% |+limit=2 |+order=desc |format=table |headers=plain }}"
+ },
+ {
+ "page": "Example/F0205/Q.3",
+ "contents": "{{#ask: [[~Example/F0205/1/*]] |?Has number |+width=50% |+align=center |+limit=2 |+order=desc |format=table |headers=plain }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0",
+ "subject": "Example/F0205/1a",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-number smwtype_num\" data-sort-value=\"0.02\" style=\"text-align:right;\">0.02<br />1",
+ "class=\"Has-number smwtype_num\" data-sort-value=\"2.02\" style=\"text-align:right;\">2.02<br />21"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (align, left)",
+ "subject": "Example/F0205/1b",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-number smwtype_num\" data-sort-value=\"42\" style=\"text-align:left;\">42<br />1",
+ "class=\"Has-number smwtype_num\" data-sort-value=\"1001\" style=\"text-align:left;\">1,001<br />21"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 (+width)",
+ "subject": "Example/F0205/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"42\" style=\"width:50%;\">42<br />1</td>",
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"1001\" style=\"width:50%;\">1,001<br />21</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 (+width, +align)",
+ "subject": "Example/F0205/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"42\" style=\"text-align:center; width:50%;\">42<br />1</td>",
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"1001\" style=\"text-align:center; width:50%;\">1,001<br />21</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0206.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0206.json
new file mode 100644
index 00000000..63119a24
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0206.json
@@ -0,0 +1,44 @@
+{
+ "description": "Test `format=table` to display extra property description `_PDESC` (en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]] [[Has property description::A number to display ....@en]]"
+ },
+ {
+ "page": "Example/F0206/1/1",
+ "contents": "[[Has number::1001]]"
+ },
+ {
+ "page": "Example/F0206/1a",
+ "contents": "{{#ask: [[~Example/F0206/1/*]] |?Has number |format=table }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0",
+ "subject": "Example/F0206/1a",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwttcontent\">A number to display ....</span>",
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"1001\">1,001</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0207.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0207.json
new file mode 100644
index 00000000..0ccd8b27
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0207.json
@@ -0,0 +1,202 @@
+{
+ "description": "Test `format=table` on formatted indent when using */#/: (en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/F0207/1/1",
+ "contents": "[[Has text::* 123 \n* 345]] [[Category:F0207]]"
+ },
+ {
+ "page": "Example/F0207/1/2",
+ "contents": "{{#subobject:|Has text=* 一二三 \n* 四五六 \nsome text without indent|@category=F0207}}"
+ },
+ {
+ "page": "Example/F0207/1/3",
+ "contents": "[[Has text::# abc \n# def]] [[Category:F0207]]"
+ },
+ {
+ "page": "Example/F0207/1/4",
+ "contents": "[[Has text::: ABC \n:: DEF]] [[Category:F0207]]"
+ },
+ {
+ "page": "Example/F0207/1/5",
+ "contents": "[[Has text::Some text * without indent]]"
+ },
+ {
+ "page": "Example/F0207/1/6",
+ "contents": "[[Has text::*Without space\n#123]]"
+ },
+ {
+ "page": "Example/F0207/1a",
+ "contents": "{{#ask: [[Category:F0207]] |?Has text |format=table |link=none}}"
+ },
+ {
+ "page": "Example/F0207/1b",
+ "contents": "{{#show: Example/F0207/1/1 |?Has text }}"
+ },
+ {
+ "page": "Example/F0207/3a",
+ "contents": "{{#show: Example/F0207/1/3 |?Has text }}"
+ },
+ {
+ "page": "Example/F0207/5a",
+ "contents": "{{#show: Example/F0207/1/5 |?Has text }}"
+ },
+ {
+ "page": "Example/F0207/6a",
+ "contents": "{{#show: Example/F0207/1/6 |?Has text }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 (1.31-)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0207/1a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/F0207/1/1</td><td class=\"Has-text smwtype_txt\">",
+ "<li> 123",
+ "<li> 345",
+ "<td class=\"smwtype_wpg\">Example/F0207/1/2#_f3c65172820fbf16a271da866298e82b</td><td class=\"Has-text smwtype_txt\">",
+ "<li> 一二三",
+ "<li> 四五六",
+ "<p>some text without indent",
+ "<td class=\"smwtype_wpg\">Example/F0207/1/3</td><td class=\"Has-text smwtype_txt\">",
+ "<li> abc",
+ "<li> def",
+ "<tr data-row-number=\"4\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/F0207/1/4</td><td class=\"Has-text smwtype_txt\">",
+ "<dd> ABC",
+ "<dd> DEF"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#0 (1.31+)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0207/1a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/F0207/1/1</td><td class=\"Has-text smwtype_txt\">",
+ "<li>123",
+ "<li>345",
+ "<td class=\"smwtype_wpg\">Example/F0207/1/2#_f3c65172820fbf16a271da866298e82b</td><td class=\"Has-text smwtype_txt\">",
+ "<li>一二三",
+ "<li>四五六",
+ "<p>some text without indent",
+ "<td class=\"smwtype_wpg\">Example/F0207/1/3</td><td class=\"Has-text smwtype_txt\">",
+ "<li>abc",
+ "<li>def",
+ "<tr data-row-number=\"4\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/F0207/1/4</td><td class=\"Has-text smwtype_txt\">",
+ "<dd>ABC",
+ "<dd>DEF"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (1.31-)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0207/1b",
+ "assert-output": {
+ "to-contain": [
+ "<ul>",
+ "<li> 123",
+ "<li> 345"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 (1.31+)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0207/1b",
+ "assert-output": {
+ "to-contain": [
+ "<ul>",
+ "<li>123",
+ "<li>345"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 (1.31-)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0207/3a",
+ "assert-output": {
+ "to-contain": [
+ "<ol>",
+ "<li> abc",
+ "<li> def"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 (1.31+)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0207/3a",
+ "assert-output": {
+ "to-contain": [
+ "<ol>",
+ "<li>abc",
+ "<li>def"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3",
+ "subject": "Example/F0207/5a",
+ "assert-output": {
+ "to-contain": [
+ "<p>Some text * without indent"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4",
+ "subject": "Example/F0207/6a",
+ "assert-output": {
+ "to-contain": [
+ "<ul>",
+ "<li>Without space",
+ "<ol>",
+ "<li>123"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0208.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0208.json
new file mode 100644
index 00000000..372d25f3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0208.json
@@ -0,0 +1,180 @@
+{
+ "description": "Test `format=table` with `limit=0` (further result links) for user/predefined properties, `mainlabel=-`, `#show` (`wgContLang=en`, `wgLang=es`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/F0208/1",
+ "contents": "[[Has text::F0208]] [[Category:F0208]]"
+ },
+ {
+ "page": "Example/F0208/Q1.1",
+ "contents": "{{#ask: [[Has text::F0208]] |?Has text |?Modification date |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q2.1",
+ "contents": "{{#ask: [[Modification date::+]] |?Modification date |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q2.2",
+ "contents": "{{#ask: [[Fecha de modificación@es::+]] |?Fecha de modificación@es |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/3",
+ "contents": "[[Has page::F0208]] {{#subobject:Has text=ABC}}"
+ },
+ {
+ "page": "Example/F0208/4",
+ "contents": "[[Has page::Example/F0208/3]]"
+ },
+ {
+ "page": "Example/F0208/Q3.1",
+ "contents": "{{#ask: [[Has page::F0208]] |mainlabel |?Has page |format=table |headers=plain |link=none |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q3.2",
+ "contents": "{{#ask: [[Has page::F0208]] |mainlabel |?Has page#Foo |format=table |headers=plain |link=none |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q3.3",
+ "contents": "{{#ask: [[Has page::F0208]] |mainlabel |?Has page# |format=table |headers=plain |link=none |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q3.4",
+ "contents": "{{#ask: [[Has page::F0208]] |mainlabel=- |?Has page |format=table |headers=plain |link=none |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q3.5",
+ "contents": "{{#show: Example/F0208/3 |mainlabel=- |?Has page |format=table |headers=plain |link=none |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q4.1",
+ "contents": "{{#ask:[[Has page::Example/F0208/3]] |mainlabel=- |?Has page.Has subobject.Has text |format=table |headers=plain |link=none |limit=0 }}"
+ },
+ {
+ "page": "Example/F0208/Q4.2",
+ "contents": "{{#ask:[[Has page::Example/F0208/3]] |mainlabel=- |?Has page.Has subobject.Has text=SomeOtherText |format=table |headers=plain |link=none |limit=0 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0",
+ "subject": "Example/F0208/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20text::F0208-5D-5D/-3FHas-20text/-3FModification-20date/mainlabel%3D/offset%3D0/format%3Dtable"
+ ],
+ "not-contain": [
+ "Special:Ask/-5B-5BHas-20text::F0208-5D-5D/-3FHas-20text-23/-3FModification-20date-23=Fecha-20de-20modificación/mainlabel=/offset=0/format=table"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 predefined properties linking to canonical properties",
+ "subject": "Example/F0208/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BModification-20date::%2B-5D-5D/-3FModification-20date/mainlabel%3D/offset%3D0/format%3Dtable"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 predefined properties linking to canonical properties",
+ "subject": "Example/F0208/Q2.2",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BModification-20date::%2B-5D-5D/-3FModification-20date/mainlabel%3D/offset%3D0/format%3Dtable"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3",
+ "subject": "Example/F0208/Q3.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0208-5D-5D/-3FHas-20page/mainlabel=/offset=0/format=table/link=none/headers=plain"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4",
+ "subject": "Example/F0208/Q3.2",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0208-5D-5D/-3FHas-20page-23Foo/mainlabel=/offset=0/format=table/link=none/headers=plain"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5",
+ "subject": "Example/F0208/Q3.3",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0208-5D-5D/-3FHas-20page-23-2D/mainlabel=/offset=0/format=table/link=none/headers=plain"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#6",
+ "subject": "Example/F0208/Q3.4",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0208-5D-5D/-3FHas-20page/mainlabel=-2D/offset=0/format=table/link=none/headers=plain"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#7 (#show)",
+ "subject": "Example/F0208/Q3.5",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5B:Example-2FF0208-2F3-5D-5D/-3FHas-20page/mainlabel=-2D/offset=0/format=table/link=none/headers=plain"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#8 (property chain on printrequest)",
+ "subject": "Example/F0208/Q4.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::Example-2FF0208-2F3-5D-5D/-3FHas-20page.Has-20subobject.Has-20text=Has-20text/mainlabel=-2D/offset=0/format=table/link=none/headers=plain"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#9 (property chain on printrequest)",
+ "subject": "Example/F0208/Q4.2",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::Example-2FF0208-2F3-5D-5D/-3FHas-20page.Has-20subobject.Has-20text=SomeOtherText/mainlabel=-2D/offset=0/format=table/link=none/headers=plain"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "es",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0209.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0209.json
new file mode 100644
index 00000000..2f4e9ff5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0209.json
@@ -0,0 +1,73 @@
+{
+ "description": "Test `format=table` on `_tem`/ `_num` with `LOCAL@...` output (#1591, `wgContLang=es`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has temperature",
+ "contents": "[[Has type::Temperature]]"
+ },
+ {
+ "page": "Example/F0209/1",
+ "contents": "{{#subobject: |Has temperature = 3,928 K |@category=F0209}}{{#subobject: |Has temperature = 113,928 K |@category=F0209 }}{{#subobject: |Has temperature = 5413,928 K |@category=F0209 }}{{#subobject: |Has temperature = 44413,928 K |@category=F0209 }}"
+ },
+ {
+ "page": "Example/F0209/Q1.1",
+ "contents": "{{#ask: [[Category:F0209]] |?Has temperature |?Has temperature#LOCL@fr=fr }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 (1.31-) different lang formatting (en for user lang + fr) rules don't interfere with each other",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0209/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwtext\">5,413.928&#160;K</span><span class=\"smwttcontent\">5,140.778&#160;°C <br />9,285.4&#160;°F <br />9,745.07&#160;°R <br />",
+ "<span class=\"smwtext\">5 413,928&#160;K</span><span class=\"smwttcontent\">5 140,778&#160;°C <br />9 285,4&#160;°F <br />9 745,07&#160;°R <br />",
+ "<span class=\"smwtext\">44,413.928&#160;K</span><span class=\"smwttcontent\">44,140.778&#160;°C <br />79,485.4&#160;°F <br />79,945.07&#160;°R <br />",
+ "<span class=\"smwtext\">44 413,928&#160;K</span><span class=\"smwttcontent\">44 140,778&#160;°C <br />79 485,4&#160;°F <br />79 945,07&#160;°R <br />",
+ "<span class=\"smwtext\">3.928&#160;K</span><span class=\"smwttcontent\">-269.222&#160;°C <br />-452.6&#160;°F <br />7.07&#160;°R <br />",
+ "<span class=\"smwtext\">3,928&#160;K</span><span class=\"smwttcontent\">-269,222&#160;°C <br />-452,6&#160;°F <br />7,07&#160;°R <br />",
+ "<span class=\"smwtext\">113.928&#160;K</span><span class=\"smwttcontent\">-159.222&#160;°C <br />-254.6&#160;°F <br />205.07&#160;°R <br />",
+ "<span class=\"smwtext\">113,928&#160;K</span><span class=\"smwttcontent\">-159,222&#160;°C <br />-254,6&#160;°F <br />205,07&#160;°R <br />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#0 (1.31+) different lang formatting (en for user lang + fr) rules don't interfere with each other",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/F0209/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwtext\">5,413.928&#160;K</span><span class=\"smwttcontent\">5,140.778&#160;°C <br />9,285.4&#160;°F <br />9,745.07&#160;°R <br />",
+ "<span class=\"smwtext\">5&#160;413,928&#160;K</span><span class=\"smwttcontent\">5&#160;140,778&#160;°C <br />9&#160;285,4&#160;°F <br />9&#160;745,07&#160;°R <br />",
+ "<span class=\"smwtext\">44,413.928&#160;K</span><span class=\"smwttcontent\">44,140.778&#160;°C <br />79,485.4&#160;°F <br />79,945.07&#160;°R <br />",
+ "<span class=\"smwtext\">44&#160;413,928&#160;K</span><span class=\"smwttcontent\">44&#160;140,778&#160;°C <br />79&#160;485,4&#160;°F <br />79&#160;945,07&#160;°R <br />",
+ "<span class=\"smwtext\">3.928&#160;K</span><span class=\"smwttcontent\">-269.222&#160;°C <br />-452.6&#160;°F <br />7.07&#160;°R <br />",
+ "<span class=\"smwtext\">3,928&#160;K</span><span class=\"smwttcontent\">-269,222&#160;°C <br />-452,6&#160;°F <br />7,07&#160;°R <br />",
+ "<span class=\"smwtext\">113.928&#160;K</span><span class=\"smwttcontent\">-159.222&#160;°C <br />-254.6&#160;°F <br />205.07&#160;°R <br />",
+ "<span class=\"smwtext\">113,928&#160;K</span><span class=\"smwttcontent\">-159,222&#160;°C <br />-254,6&#160;°F <br />205,07&#160;°R <br />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "es",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0210.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0210.json
new file mode 100644
index 00000000..b0266798
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0210.json
@@ -0,0 +1,76 @@
+{
+ "description": "Test `format=table` on `_qty` for unit labels with spaces (#1718, `wgContLang=en`, `SMW_DV_NUMV_USPACE`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area with spaces",
+ "contents": "[[Has type::Quantity]], [[Corresponds to::1 km², km ²]] [[Corresponds to::0.38610 sq mi, sqmi]] [[Corresponds to::1000 m², m ²]]"
+ },
+ {
+ "page": "Example/F0210/1",
+ "contents": "[[Has area with spaces::10 km ²]] [[Has area with spaces::3 sqmi]] [[Has area with spaces::50 m ²]] [[Category:F0210]]"
+ },
+ {
+ "page": "Example/F0210/Q1.1",
+ "contents": "{{#ask: [[Category:F0210]][[Has area with spaces::+]] |?Has area with spaces |format=table |headers=plain }}"
+ },
+ {
+ "page": "Example/F0210/Q1.2",
+ "contents": "{{#ask: [[Has area with spaces::10 km ²]] |format=table |headers=plain |link=none }}"
+ },
+ {
+ "page": "Example/F0210/Q1.3",
+ "contents": "{{#ask: [[Has area with spaces::10 km²]] |format=table |headers=plain |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0",
+ "subject": "Example/F0210/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwtext\">10&#160;km²</span><span class=\"smwttcontent\">3.861&#160;sq mi <br />10,000&#160;m² <br /></span></span>",
+ "<span class=\"smwtext\">7.77&#160;km²</span><span class=\"smwttcontent\">3&#160;sq mi <br />7,770.008&#160;m² <br /></span></span>",
+ "<span class=\"smwtext\">0.05&#160;km²</span><span class=\"smwttcontent\">0.0193&#160;sq mi <br />50&#160;m² <br /></span></span>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1",
+ "subject": "Example/F0210/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/F0210/1</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2",
+ "subject": "Example/F0210/Q1.3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/F0210/1</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDVFeatures": [
+ "SMW_DV_NUMV_USPACE"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0211.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0211.json
new file mode 100644
index 00000000..f0acea4f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0211.json
@@ -0,0 +1,230 @@
+{
+ "description": "Test `format=plainlist` with `limit=0` (further result links) for `mainlabel/?#...` (#481)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/F0211/1",
+ "contents": "[[Has text::F0211]] [[Has page::F0211]] [[Category:F0211]]"
+ },
+ {
+ "page": "Example/F0211/Q1.1",
+ "contents": "{{#ask: [[Has page::F0211]] |?#=Foo |?Has page |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q1.2",
+ "contents": "{{#ask: [[Has page::F0211]] |?#=Foo |?Has page |format=plainlist |template=Template/F0211 |named args=yes |limit=0 |mainlabel=- }}"
+ },
+ {
+ "page": "Example/F0211/Q1.3",
+ "contents": "{{#ask: [[Has page::F0211]] |?#=Foo# |?Has page |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q1.4",
+ "contents": "{{#ask: [[Has page::F0211]] |?#=Foo#- |?Has page |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q2.1",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |format=plainlist |template=Template/F0211 |named args=yes |limit=0 |mainlabel= }}"
+ },
+ {
+ "page": "Example/F0211/Q2.2",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |format=plainlist |template=Template/F0211 |named args=yes |limit=0 |mainlabel=- }}"
+ },
+ {
+ "page": "Example/F0211/Q2.3",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |format=plainlist |template=Template/F0211 |named args=yes |limit=0 |mainlabel=FOO }}"
+ },
+ {
+ "page": "Example/F0211/Q3.1",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |?# | mainlabel= |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q3.2",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |?#- | mainlabel= |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q3.3",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |?#- | mainlabel=- |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q3.4",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |?#- | mainlabel=FOO |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q4.1",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |? | mainlabel= |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q4.2",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |?- | mainlabel= |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ },
+ {
+ "page": "Example/F0211/Q4.3",
+ "contents": "{{#ask: [[Has page::F0211]] |?Has page |?=Foo | mainlabel= |format=plainlist |template=Template/F0211 |named args=yes |limit=0 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0",
+ "subject": "Example/F0211/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3F-23%3DFoo/-3FHas-20page/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1",
+ "subject": "Example/F0211/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3F-23%3DFoo/-3FHas-20page/mainlabel%3D-2D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2",
+ "subject": "Example/F0211/Q1.3",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3F-23%3DFoo-23-2D/-3FHas-20page/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 (link is the same as in #2 due to `-`)",
+ "subject": "Example/F0211/Q1.4",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3F-23%3DFoo-23-2D/-3FHas-20page/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 (mainlabel)",
+ "subject": "Example/F0211/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 (mainlabel)",
+ "subject": "Example/F0211/Q2.2",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/mainlabel%3D-2D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#6 (mainlabel)",
+ "subject": "Example/F0211/Q2.3",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/mainlabel%3DFOO/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#7",
+ "subject": "Example/F0211/Q3.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/-3F-23/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#8",
+ "subject": "Example/F0211/Q3.2",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/-3F-23-2D/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#9",
+ "subject": "Example/F0211/Q3.3",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/-3F-23-2D/mainlabel%3D-2D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#10",
+ "subject": "Example/F0211/Q3.4",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/-3F-23-2D/mainlabel%3DFOO/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#11",
+ "subject": "Example/F0211/Q4.1",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/-3F/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#12 (?- is not valid and is therefore ignored)",
+ "subject": "Example/F0211/Q4.2",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#13",
+ "subject": "Example/F0211/Q4.3",
+ "assert-output": {
+ "to-contain": [
+ "Special:Ask/-5B-5BHas-20page::F0211-5D-5D/-3FHas-20page/-3F%3DFoo/mainlabel%3D/offset%3D0/format%3Dplainlist/template%3DTemplate-2FF0211/named-20args%3Dyes"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0301.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0301.json
new file mode 100644
index 00000000..85f9992b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0301.json
@@ -0,0 +1,212 @@
+{
+ "description": "Test `format=category` with template usage (#699, en, skip postgres)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "UseNamedArgsTemplateForColumnOutput",
+ "contents": "<includeonly>{{{1}}}, {{{Has page property}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "UseUnnamedArgsTemplateForColumnOutput",
+ "contents": "<includeonly>{{{1}}}, {{{2}}}</includeonly>"
+ },
+ {
+ "page": "Foo",
+ "contents": "[[Has page property::Test]]"
+ },
+ {
+ "page": "Bar",
+ "contents": "[[Has page property::Test]]"
+ },
+ {
+ "page": "123",
+ "contents": "[[Has page property::Test]] [[Has page property::Test2]]"
+ },
+ {
+ "page": "テスト",
+ "contents": "[[Has page property::Test]]"
+ },
+ {
+ "page": "είναι απλά",
+ "contents": "[[Has page property::Test2]] {{DEFAULTSORT:A}}"
+ },
+ {
+ "page": "је једноÑтавно модел",
+ "contents": "[[Has page property::Test2]] {{DEFAULTSORT:B}}"
+ },
+ {
+ "page": "template-output-named-args-asc",
+ "contents": "{{#ask:[[Has page property::Test]]\n |?Has page property\n |format=category\n |order=asc\n |link=none\n |limit=10\n |template=UseNamedArgsTemplateForColumnOutput\n ||named args=yes\n}}"
+ },
+ {
+ "page": "template-output-named-args-desc",
+ "contents": "{{#ask:[[Has page property::Test]]\n |?Has page property\n |format=category\n |order=desc\n |link=none\n |limit=10\n |template=UseNamedArgsTemplateForColumnOutput\n ||named args=yes\n}}"
+ },
+ {
+ "page": "template-output-unnamed-args-asc",
+ "contents": "{{#ask:[[Has page property::Test]]\n |?Has page property\n |format=category\n |order=asc\n |link=none\n |limit=10\n |template=UseUnnamedArgsTemplateForColumnOutput\n ||named args=no\n}}"
+ },
+ {
+ "page": "template-output-unnamed-args-desc",
+ "contents": "{{#ask:[[Has page property::Test]]\n |?Has page property\n |format=category\n |order=desc\n |link=none\n |limit=10\n |template=UseUnnamedArgsTemplateForColumnOutput\n ||named args=no\n}}"
+ },
+ {
+ "page": "one-column-plainlist-output-asc",
+ "contents": "{{#ask:[[Has page property::Test]]\n |?Has page property\n |format=category\n |order=asc\n |link=none\n |headers=plain |limit=10\n |columns=1\n}}"
+ },
+ {
+ "page": "limited-two-column-plainlist-output-desc",
+ "contents": "{{#ask:[[Has page property::Test]]\n |?Has page property\n |format=category\n |order=desc\n |link=none\n |headers=plain\n |searchlabel=Test more\n |limit=2\n |columns=2\n}}"
+ },
+ {
+ "page": "one-column-plainlist-output-with-default-sort-asc",
+ "contents": "{{#ask:[[Has page property::Test2]]\n |?Has page property\n |format=category\n |order=asc\n |link=none\n |headers=plain |limit=10\n |columns=1\n}}"
+ },
+ {
+ "page": "template-output-unnamed-args-with-default-sort-asc",
+ "contents": "{{#ask:[[Has page property::Test2]]\n |?Has page property\n |format=category\n |order=asc\n |link=none\n |limit=10\n |template=UseUnnamedArgsTemplateForColumnOutput\n ||named args=no\n}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0",
+ "subject": "template-output-named-args-asc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">1</div><ul><li>123, Test Test2</li></ul>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Bar, Test</li></ul></div>",
+ "<div class=\"smw-column-header\">F</div><ul><li>Foo, Test</li></ul>",
+ "<div class=\"smw-column-header\">テ</div><ul><li>テスト, Test</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1",
+ "subject": "template-output-named-args-desc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">テ</div><ul><li>テスト, Test</li></ul>",
+ "<div class=\"smw-column-header\">F</div><ul><li>Foo, Test</li></ul></div>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Bar, Test</li></ul>",
+ "<div class=\"smw-column-header\">1</div><ul><li>123, Test Test2</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2",
+ "subject": "template-output-unnamed-args-asc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">1</div><ul><li>123, Test Test2</li></ul>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Bar, Test</li></ul></div>",
+ "<div class=\"smw-column-header\">F</div><ul><li>Foo, Test</li></ul>",
+ "<div class=\"smw-column-header\">テ</div><ul><li>テスト, Test</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3",
+ "subject": "template-output-unnamed-args-desc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">テ</div><ul><li>テスト, Test</li></ul>",
+ "<div class=\"smw-column-header\">F</div><ul><li>Foo, Test</li></ul></div>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Bar, Test</li></ul>",
+ "<div class=\"smw-column-header\">1</div><ul><li>123, Test Test2</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4",
+ "subject": "one-column-plainlist-output-asc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">1</div><ul><li>123 (Has page property Test, Test2)</li></ul>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Bar (Has page property Test)</li></ul>",
+ "<div class=\"smw-column-header\">F</div><ul><li>Foo (Has page property Test)</li></ul>",
+ "<div class=\"smw-column-header\">テ</div><ul><li>テスト (Has page property Test)</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5",
+ "subject": "limited-two-column-plainlist-output-desc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">テ</div><ul><li>テスト (Has page property Test)</li></ul>",
+ "<div class=\"smw-column-header\">F</div><ul><li>Foo (Has page property Test)</li></ul></div>",
+ "<div class=\"smw-column\" style=\"width:50%;\" dir=\"ltr\"><div class=\"smw-column-header\">F cont.</div><ul><li>",
+ "Special:Ask/-5B-5BHas-20page-20property::Test-5D-5D/-3FHas-20page-20property/mainlabel=/limit=2/order=desc/sort=/offset=2/format=category/link=none/headers=plain/searchlabel=Test-20more/columns=2\">Test more</a></span></li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#6, refs #699",
+ "subject": "one-column-plainlist-output-with-default-sort-asc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column\" style=\"width:100%;\" dir=\"ltr\"><div class=\"smw-column-header\">1</div><ul><li>123 (Has page property Test, Test2)</li></ul>",
+ "<div class=\"smw-column-header\">A</div><ul><li>Είναι απλά (Has page property Test2)</li></ul>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Је једноÑтавно модел (Has page property Test2)</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#7, refs #699",
+ "subject": "template-output-unnamed-args-with-default-sort-asc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column\" style=\"width:33%;\" dir=\"ltr\"><div class=\"smw-column-header\">1</div><ul><li>123, Test Test2</li></ul></div>",
+ "<div class=\"smw-column\" style=\"width:33%;\" dir=\"ltr\"><div class=\"smw-column-header\">A</div><ul><li>Είναι απλά, Test2</li></ul></div>",
+ "<div class=\"smw-column\" style=\"width:33%;\" dir=\"ltr\"><div class=\"smw-column-header\">B</div><ul><li>Је једноÑтавно модел, Test2</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "Unicode needs special treatment in postgres"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0302.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0302.json
new file mode 100644
index 00000000..6e82788a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0302.json
@@ -0,0 +1,108 @@
+{
+ "description": "Test `format=category` and defaultsort (#699, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Saaa",
+ "contents": "[[Has text::aaa]] [[Has text::aba]] [[Has text::abb]]"
+ },
+ {
+ "page": "Sbaa",
+ "contents": "[[Has text::baa]] {{DEFAULTSORT:Saba}}"
+ },
+ {
+ "page": "Scba",
+ "contents": "[[Has text::cba]] [[Has text::01]] [[Has text::10]]"
+ },
+ {
+ "page": "Seba",
+ "contents": "[[Has text::eba]]"
+ },
+ {
+ "page": "Seoa",
+ "contents": "[[Has text::eoa]] {{DEFAULTSORT:Saca}}"
+ },
+ {
+ "page": "Soaa",
+ "contents": "[[Has text::oaa]]"
+ },
+ {
+ "page": "one-column-plainlist-output-asc",
+ "contents": "{{#ask:[[Has text::+]]\n |?Has text\n |format=category\n |order=asc\n |link=none\n |headers=plain\n |delim=;\n |limit=10\n |columns=1\n}}"
+ },
+ {
+ "page": "one-column-plainlist-output-desc",
+ "contents": "{{#ask:[[Has text::+]]\n |?Has text\n |format=category\n |order=desc\n |link=none\n |headers=plain\n |limit=10\n |columns=1\n}}"
+ },
+ {
+ "page": "Example/0302/Further-link",
+ "contents": "{{#ask:[[Has text::+]]\n |?Has text\n |format=category\n |order=desc\n |link=none\n |headers=plain\n |limit=0\n |columns=1\n}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0",
+ "subject": "one-column-plainlist-output-asc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">S</div><ul>",
+ "<li>Saaa (Has text aaa; aba; abb)</li>",
+ "<li>Sbaa (Has text baa)</li>",
+ "<li>Seoa (Has text eoa)</li>",
+ "<li>Scba (Has text 01; 10; cba)</li>",
+ "<li>Seba (Has text eba)</li>",
+ "<li>Soaa (Has text oaa)</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1",
+ "subject": "one-column-plainlist-output-desc",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">S</div><ul>",
+ "<li>Soaa (Has text oaa)</li>",
+ "<li>Seba (Has text eba)</li>",
+ "<li>Scba (Has text 01, 10, cba)</li>",
+ "<li>Seoa (Has text eoa)</li>",
+ "<li>Sbaa (Has text baa)</li>",
+ "<li>Saaa (Has text aaa, aba, abb)</li></ul></div>",
+ "<br style=\"clear: both;\" />"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 Further link",
+ "subject": "Example/0302/Further-link",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-category-furtherresults\">",
+ "Special:Ask/-5B-5BHas-20text::+-5D-5D/-3FHas-20text/mainlabel=/order=desc/sort=/offset=0/format=category/link=none/headers=plain/columns=1"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0303.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0303.json
new file mode 100644
index 00000000..40f3cc9c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0303.json
@@ -0,0 +1,150 @@
+{
+ "description": "Test `format=category` sort output using a template and DEFAULTSORT (#1459, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has surname",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has given name",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has initials",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "CategoryListTemplate",
+ "contents": "<includeonly>{{{1}}}, {{{3}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "SetSobjWithSort",
+ "contents": "<includeonly>{{#subobject:|Has surname={{{Has surname}}}|Has given name={{{Has given name}}}|Has initials={{{Has initials}}}|@category={{{Category}}}|@sortkey={{{Has surname}}},{{{Has initials}}} }}</includeonly>"
+ },
+ {
+ "page": "Example/F0303/1",
+ "contents": "{{#subobject:|Has surname=Abbot|Has given name=John|Has initials=J.|@category=SOBJ1459}}{{#subobject: |Has surname=Arthur|Has given name=Frank Walter|Has initials=F.W.|@category=SOBJ1459}}{{#subobject: |Has surname=Baker|Has given name=George Henry|Has initials=G.H.|@category=SOBJ1459}}"
+ },
+ {
+ "page": "Example/F0303/1aq",
+ "contents": "{{#ask: [[Category:SOBJ1459]] |?Has surname# |?Has given name# |?Has initials# |format=category |mainlabel=- |template=CategoryListTemplate |sort=Has surname,Has initials }}"
+ },
+ {
+ "page": "Example/F0303/1bq",
+ "contents": "{{#ask: [[Category:SOBJ1459]] |?Has surname# |?Has given name# |?Has initials# |format=category |mainlabel=- |headers=hide |sort=Has surname,Has initials }}"
+ },
+ {
+ "page": "Example/F0303/2/1",
+ "contents": "[[Has surname::Abbot]] [[Has given name::John]] [[Has initials::J.]] [[Category:PAGE1459]] {{DEFAULTSORT:Abbot}}"
+ },
+ {
+ "page": "Example/F0303/2/2",
+ "contents": "[[Has surname::Arthur]] [[Has given name::Frank Walter]] [[Has initials::F.W.]] [[Category:PAGE1459]] {{DEFAULTSORT:Arthur}}"
+ },
+ {
+ "page": "Example/F0303/2/3",
+ "contents": "[[Has surname::Baker]] [[Has given name::George Henry]] [[Has initials::G.H.]] [[Category:PAGE1459]] {{DEFAULTSORT:Baker}}"
+ },
+ {
+ "page": "Example/F0303/2aq",
+ "contents": "{{#ask: [[Category:PAGE1459]] |?Has surname# |?Has given name# |?Has initials# |format=category |mainlabel=- |template=CategoryListTemplate |sort=Has surname,Has initials }}"
+ },
+ {
+ "page": "Example/F0303/2bq",
+ "contents": "{{#ask: [[Category:PAGE1459]] |?Has surname# |?Has given name# |?Has initials# |format=category |mainlabel=- |headers=hide |sort=Has surname,Has initials }}"
+ },
+ {
+ "page": "Example/F0303/3",
+ "contents": "{{SetSobjWithSort|Has surname=Abbot|Has given name=John|Has initials=J.|Category=SOBJSORT1459}}{{SetSobjWithSort|Has surname=Arthur|Has given name=Frank Walter|Has initials=F.W.|Category=SOBJSORT1459}}{{SetSobjWithSort|Has surname=Baker|Has given name=George Henry|Has initials=G.H.|Category=SOBJSORT1459}}"
+ },
+ {
+ "page": "Example/F0303/3aq",
+ "contents": "{{#ask: [[Category:SOBJSORT1459]] |?Has surname# |?Has given name# |?Has initials# |format=category |mainlabel=- |template=CategoryListTemplate |sort=Has surname,Has initials }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 using sobj",
+ "subject": "Example/F0303/1aq",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">A</div><ul><li>Abbot, J.</li></ul></div>",
+ "<div class=\"smw-column-header\">A cont.</div><ul><li>Arthur, F.W.</li></ul></div>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Baker, G.H.</li></ul></div>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 using sobj",
+ "subject": "Example/F0303/1bq",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">A</div><ul><li>Abbot (John J.)</li></ul></div>",
+ "<div class=\"smw-column-header\">A cont.</div><ul><li>Arthur (Frank Walter F.W.)</li></ul></div>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Baker (George Henry G.H.)</li></ul></div>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2",
+ "subject": "Example/F0303/2aq",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">A</div><ul><li>Abbot, J.</li></ul></div>",
+ "<div class=\"smw-column-header\">A cont.</div><ul><li>Arthur, F.W.</li></ul></div>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Baker, G.H.</li></ul></div>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3",
+ "subject": "Example/F0303/2bq",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">A</div><ul><li>Abbot (John J.)</li></ul></div>",
+ "<div class=\"smw-column-header\">A cont.</div><ul><li>Arthur (Frank Walter F.W.)</li></ul></div>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Baker (George Henry G.H.)</li></ul></div>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 using sobj",
+ "subject": "Example/F0303/3aq",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-columnlist-container\" dir=\"ltr\">",
+ "<div class=\"smw-column-header\">A</div><ul><li>Abbot, J.</li></ul></div>",
+ "<div class=\"smw-column-header\">A cont.</div><ul><li>Arthur, F.W.</li></ul></div>",
+ "<div class=\"smw-column-header\">B</div><ul><li>Baker, G.H.</li></ul></div>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0304.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0304.json
new file mode 100644
index 00000000..46a546ee
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0304.json
@@ -0,0 +1,198 @@
+{
+ "description": "Test `format=category` with identity collation sort (#2065, `smwgEntityCollation=identity`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Chiapas",
+ "contents": "[[Has page::Chiapas]] [[Category:F0304-1]]"
+ },
+ {
+ "page": "Colima",
+ "contents": "[[Has page::Colima]] [[Category:F0304-1]]"
+ },
+ {
+ "page": "Cinco Rios",
+ "contents": "[[Has page::Cinco Rios]] [[Category:F0304-1]]"
+ },
+ {
+ "page": "California",
+ "contents": "[[Has page::California]] [[Category:F0304-1]]"
+ },
+ {
+ "page": "Example/F0304/Q.1.1",
+ "contents": "{{#ask: [[Category:F0304-1]] |?Has page |format=category |sort=# |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0304/Q.1.2",
+ "contents": "{{#ask: [[Category:F0304-1]] |?Has page |format=category |sort=# |order=desc |link=none }}"
+ },
+ {
+ "page": "Example/F0304/Q.1.3",
+ "contents": "{{#ask: [[Category:F0304-1]] |?Has page |format=category |sort= |order=desc |link=none }}"
+ },
+ {
+ "page": "Example/F0304/Q.1.4",
+ "contents": "{{#ask: [[Category:F0304-1]] |?Has page |format=category |sort=Has page |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0304/Q.1.5",
+ "contents": "{{#ask: [[Category:F0304-1]] |?Has page |format=category |sort=Has page |order=desc |link=none }}"
+ },
+ {
+ "page": "Robin Hood and Little John (Aslackby)",
+ "contents": "[[Has page::Robin Hood and Little John (Aslackby)]] [[Category:F0304-2]]"
+ },
+ {
+ "page": "Robin Hood Tavern (Upper Clapton)",
+ "contents": "[[Has page::Robin Hood Tavern (Upper Clapton)]] [[Category:F0304-2]]"
+ },
+ {
+ "page": "Example/F0304/Q.2.1",
+ "contents": "{{#ask: [[Category:F0304-2]] |?Has page |format=category |sort= |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0304/Q.2.2",
+ "contents": "{{#ask: [[Category:F0304-2]] |?Has page |format=category |sort= |order=desc |link=none }}"
+ },
+ {
+ "page": "b9",
+ "contents": "[[Has page::b9]] [[Category:F0304-3]]"
+ },
+ {
+ "page": "b1000",
+ "contents": "[[Has page::b1000]] [[Category:F0304-3]]"
+ },
+ {
+ "page": "Example/F0304/Q.3.1",
+ "contents": "{{#ask: [[Category:F0304-3]] |?Has page |format=category |sort= |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0304/Q.3.2",
+ "contents": "{{#ask: [[Category:F0304-3]] |?Has page |format=category |sort= |order=desc |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 asc",
+ "subject": "Example/F0304/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>California.*</li><li>Chiapas.*<li>Cinco Rios.*</li><li>Colima"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 desc",
+ "subject": "Example/F0304/Q.1.2",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>Colima.*</li><li>Cinco Rios.*<li>Chiapas.*</li><li>California"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 desc",
+ "subject": "Example/F0304/Q.1.3",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>Colima.*</li><li>Cinco Rios.*<li>Chiapas.*</li><li>California"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 Has page,asc",
+ "subject": "Example/F0304/Q.1.4",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>California.*</li><li>Chiapas.*<li>Cinco Rios.*</li><li>Colima"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 Has page,desc",
+ "subject": "Example/F0304/Q.1.5",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>Colima.*</li><li>Cinco Rios.*<li>Chiapas.*</li><li>California"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#6 asc",
+ "subject": "Example/F0304/Q.2.1",
+ "skip-on": {
+ "postgres": "Contains the reverted order of MySQL!",
+ "sqlite": "Contains the reverted order of MySQL!"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<ul><li>Robin Hood Tavern (Upper Clapton).*<li>Robin Hood and Little John (Aslackby)"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#7 desc",
+ "subject": "Example/F0304/Q.2.2",
+ "skip-on": {
+ "postgres": "Contains the reverted order of MySQL!",
+ "sqlite": "Contains the reverted order of MySQL!"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<ul><li>Robin Hood and Little John (Aslackby).*<li>Robin Hood Tavern (Upper Clapton)"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#8 asc",
+ "subject": "Example/F0304/Q.3.1",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B1000.*<li>B9"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#9 desc",
+ "subject": "Example/F0304/Q.3.2",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B9.*<li>B1000"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEntityCollation": "identity",
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_REDI",
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC",
+ "SMW_SPARQL_QF_COLLATION"
+ ],
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0305.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0305.json
new file mode 100644
index 00000000..e55e04e8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0305.json
@@ -0,0 +1,190 @@
+{
+ "description": "Test `format=category` with uppercase collation sort (#2065, `smwgEntityCollation=uppercase`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Chiapas",
+ "contents": "[[Has page::Chiapas]] [[Category:F0305-1]]"
+ },
+ {
+ "page": "Colima",
+ "contents": "[[Has page::Colima]] [[Category:F0305-1]]"
+ },
+ {
+ "page": "Cinco Rios",
+ "contents": "[[Has page::Cinco Rios]] [[Category:F0305-1]]"
+ },
+ {
+ "page": "California",
+ "contents": "[[Has page::California]] [[Category:F0305-1]]"
+ },
+ {
+ "page": "Example/F0305/Q.1.1",
+ "contents": "{{#ask: [[Category:F0305-1]] |?Has page |format=category |sort=# |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0305/Q.1.2",
+ "contents": "{{#ask: [[Category:F0305-1]] |?Has page |format=category |sort=# |order=desc |link=none }}"
+ },
+ {
+ "page": "Example/F0305/Q.1.3",
+ "contents": "{{#ask: [[Category:F0305-1]] |?Has page |format=category |sort= |order=desc |link=none }}"
+ },
+ {
+ "page": "Example/F0305/Q.1.4",
+ "contents": "{{#ask: [[Category:F0305-1]] |?Has page |format=category |sort=Has page |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0305/Q.1.5",
+ "contents": "{{#ask: [[Category:F0305-1]] |?Has page |format=category |sort=Has page |order=desc |link=none }}"
+ },
+ {
+ "page": "Robin Hood and Little John (Aslackby)/2",
+ "contents": "[[Has page::Robin Hood and Little John (Aslackby)]] [[Category:F0305-2]]"
+ },
+ {
+ "page": "Robin Hood Tavern (Upper Clapton)/2",
+ "contents": "[[Has page::Robin Hood Tavern (Upper Clapton)]] [[Category:F0305-2]]"
+ },
+ {
+ "page": "Example/F0305/Q.2.1",
+ "contents": "{{#ask: [[Category:F0305-2]] |?Has page |format=category |sort= |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0305/Q.2.2",
+ "contents": "{{#ask: [[Category:F0305-2]] |?Has page |format=category |sort= |order=desc |link=none }}"
+ },
+ {
+ "page": "b9",
+ "contents": "[[Has page::b9]] [[Category:F0305-3]]"
+ },
+ {
+ "page": "b1000",
+ "contents": "[[Has page::b1000]] [[Category:F0305-3]]"
+ },
+ {
+ "page": "Example/F0305/Q.3.1",
+ "contents": "{{#ask: [[Category:F0305-3]] |?Has page |format=category |sort= |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0305/Q.3.2",
+ "contents": "{{#ask: [[Category:F0305-3]] |?Has page |format=category |sort= |order=desc |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 asc",
+ "subject": "Example/F0305/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>California.*</li><li>Chiapas.*<li>Cinco Rios.*</li><li>Colima"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 desc",
+ "subject": "Example/F0305/Q.1.2",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>Colima.*</li><li>Cinco Rios.*<li>Chiapas.*</li><li>California"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 desc",
+ "subject": "Example/F0305/Q.1.3",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>Colima.*</li><li>Cinco Rios.*<li>Chiapas.*</li><li>California"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 Has page,asc",
+ "subject": "Example/F0305/Q.1.4",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>California.*</li><li>Chiapas.*<li>Cinco Rios.*</li><li>Colima"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 Has page,desc",
+ "subject": "Example/F0305/Q.1.5",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">C</div><ul><li>Colima.*</li><li>Cinco Rios.*<li>Chiapas.*</li><li>California"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#6 asc (different to f-0304)",
+ "subject": "Example/F0305/Q.2.1",
+ "assert-output": {
+ "to-contain": [
+ "<ul><li>Robin Hood and Little John (Aslackby).*<li>Robin Hood Tavern (Upper Clapton)"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#7 desc (different to f-0304)",
+ "subject": "Example/F0305/Q.2.2",
+ "assert-output": {
+ "to-contain": [
+ "<ul><li>Robin Hood Tavern (Upper Clapton).*<li>Robin Hood and Little John (Aslackby)"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#8 asc",
+ "subject": "Example/F0305/Q.3.1",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B1000.*<li>B9"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#9 desc",
+ "subject": "Example/F0305/Q.3.2",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B9.*<li>B1000"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEntityCollation": "uppercase",
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_REDI",
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC",
+ "SMW_SPARQL_QF_COLLATION"
+ ],
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0306.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0306.json
new file mode 100644
index 00000000..47b7779a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0306.json
@@ -0,0 +1,234 @@
+{
+ "description": "Test `format=category` with numeric collation sort (same as uppercase, but with numeric sorting) (#2065, `smwgEntityCollation=numeric`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "b9/3",
+ "contents": "[[Has page::b9]] [[Category:F0306-1]]"
+ },
+ {
+ "page": "b1000/3",
+ "contents": "[[Has page::b1000]] [[Category:F0306-1]]"
+ },
+ {
+ "page": "Example/F0306/1",
+ "contents": {
+ "import-from": "/../Fixtures/numeric-sorting.txt"
+ }
+ },
+ {
+ "page": "Example/F0306/Q.1.1",
+ "contents": "{{#ask: [[Category:F0306-1]] |?Has page |format=category |sort= |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0306/Q.1.2",
+ "contents": "{{#ask: [[Category:F0306-1]] |?Has page |format=category |sort= |order=desc |link=none }}"
+ },
+ {
+ "page": "Example/F0306/Q.1.3",
+ "contents": "{{#ask: [[Category:F0306-1]] |?Has page |format=category |sort=Has page |order=asc |link=none }}"
+ },
+ {
+ "page": "Example/F0306/Q.1.4",
+ "contents": "{{#ask: [[Category:F0306-1]] |?Has page |format=category |sort=Has page |order=desc |link=none }}"
+ },
+ {
+ "page": "Example/F0306/Q.2.1",
+ "contents": "{{#ask: [[Category:Numeric sorting example]] |?Has page |format=category |sort=Has page |order=asc |link=none |mainlabel=- |headers=hide }}"
+ },
+ {
+ "page": "Example/F0306/Q.2.2",
+ "contents": "{{#ask: [[Category:Numeric sorting example]] |?Has page |format=category |sort=Has page |order=desc |link=none |mainlabel=- |headers=hide }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 asc (different to f-0305, f-0304)",
+ "skip-on":{
+ "elastic": "Different sorting behaviour on sortkey value like B01000/03, B09/03"
+ },
+ "subject": "Example/F0306/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B9.*<li>B1000"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#0.elastic asc (different to f-0305, f-0304)",
+ "skip-on":{
+ "elastic": [ "not", "Only relevant when used in connection with ES" ]
+ },
+ "subject": "Example/F0306/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B1000.*<li>B9.*"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 desc (different to f-0305, f-0304)",
+ "skip-on":{
+ "elastic": "Different sorting behaviour on sortkey value like B01000/03, B09/03",
+ "postgres": "PostgreSQL `numeric` collation generates a different order when compared with MySQL, SQLite."
+ },
+ "subject": "Example/F0306/Q.1.2",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B1000.*<li>B9"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1.elastic desc (different to f-0305, f-0304)",
+ "skip-on":{
+ "elastic": [ "not", "Only relevant when used in connection with ES" ]
+ },
+ "subject": "Example/F0306/Q.1.2",
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B9.*<li>B1000"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 Has page, asc (different to f-0305, f-0304)",
+ "subject": "Example/F0306/Q.1.3",
+ "skip-on": {
+ "elastic": "Different sorting behaviour on sortkey value like B01000/03, B09/03",
+ "hhvm-*": "HHVM (or SQLite) shows opposite B1000, B9"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B9.*<li>B1000"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2.elastic Has page, asc (different to f-0305, f-0304)",
+ "subject": "Example/F0306/Q.1.3",
+ "skip-on":{
+ "elastic": [ "not", "Only relevant when used in connection with ES" ]
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B1000.*<li>B9"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 Has page, desc (different to f-0305, f-0304)",
+ "subject": "Example/F0306/Q.1.4",
+ "skip-on": {
+ "elastic": "Different sorting behaviour on sortkey value like B01000/03, B09/03",
+ "hhvm-*": "HHVM (or SQLite) shows opposite B9, B1000"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B1000.*<li>B9"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3.elastic Has page, desc (different to f-0305, f-0304)",
+ "subject": "Example/F0306/Q.1.4",
+ "skip-on": {
+ "elastic": [ "not", "Only relevant when used in connection with ES" ]
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">B</div><ul><li>B9.*<li>B1000"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 Has page, asc, imported content",
+ "subject": "Example/F0306/Q.2.1",
+ "skip-on": {
+ "elastic": "Different sorting behaviour, natural",
+ "postgres": "PostgreSQL `numeric` collation generates a different order (natural, An-2, An-218, An-22, An-225, An-24, An-3) when compared with the MySQL output."
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">A</div><ul><li>Antonov An-2.*<li>Antonov An-3 </li>.*<li>Antonov An-22 </li>.*<li>Antonov An-24 </li>.*<li>Antonov An-218 </li>.*<li>Antonov An-225 </li>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4.elastic Has page, asc, imported content",
+ "subject": "Example/F0306/Q.2.1",
+ "skip-on": {
+ "elastic": [ "not", "Only relevant when used in connection with ES" ]
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">A</div><ul><li>Antonov An-2.*<li>Antonov An-218 </li>.*<li>Antonov An-22 </li>.*<li>Antonov An-225 </li>.*<li>Antonov An-24 </li>.*<li>Antonov An-3 </li>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 Has page, desc, imported content",
+ "subject": "Example/F0306/Q.2.2",
+ "skip-on": {
+ "elastic": "Different sorting behaviour, natural",
+ "postgres": "PostgreSQL `numeric` collation generates a different order (natural, An-2, An-218, An-22, An-225, An-24, An-3) when compared with the MySQL output."
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">A</div><ul><li>Antonov An-225.*<li>Antonov An-218 </li>.*<li>Antonov An-24 </li>.*<li>Antonov An-22 </li>.*<li>Antonov An-3 </li>.*<li>Antonov An-2 </li>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5.elastic Has page, desc, imported content",
+ "subject": "Example/F0306/Q.2.2",
+ "skip-on": {
+ "elastic": [ "not", "Only relevant when used in connection with ES" ]
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-column-header\">A</div><ul><li>Antonov An-3.*<li>Antonov An-24 </li>.*<li>Antonov An-225 </li>.*<li>Antonov An-22 </li>.*<li>Antonov An-218 </li>.*<li>Antonov An-2 </li>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEntityCollation": "numeric",
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_REDI",
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC",
+ "SMW_SPARQL_QF_COLLATION"
+ ],
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "mw-1.28<": "`numeric` collation only available with 1.28+"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0307.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0307.json
new file mode 100644
index 00000000..c3a9079f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0307.json
@@ -0,0 +1,150 @@
+{
+ "description": "Test `format=table` with natural printout sorting (n-asc, n-desc)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Example/F0307/1",
+ "contents": "[[Category:F0307-Text]] [[Has text::1.4.4.8.3.1]] [[Has text::1.4.4.8.3.2]] [[Has text::1.4.4.8.3.3]] [[Has text::1.4.4.8.3.4]] [[Has text::1.4.4.8.3.5]] [[Has text::1.4.4.8.3.6]] [[Has text::1.4.4.8.3.7]] [[Has text::1.4.4.8.3.8]] [[Has text::1.4.4.8.3.9]] [[Has text::1.4.4.8.3.10]] [[Has text::1.4.4.8.3.11]] [[Has text::1.4.4.8.3.12]] [[Has text::1.4.4.8.3.1001]]"
+ },
+ {
+ "page": "Example/F0307/2",
+ "contents": "[[Category:F0307-Number]] [[Has number::1]] [[Has number::2]] [[Has number::3]] [[Has number::4]] [[Has number::5]] [[Has number::6]] [[Has number::7]] [[Has number::8]] [[Has number::9]] [[Has number::10]] [[Has number::11]] [[Has number::12]] [[Has number::1001]]"
+ },
+ {
+ "page": "Example/F0307/Q.1.1",
+ "contents": "{{#ask: [[Category:F0307-Text]] |?Has text|+order=asc |format=table |link=none }}"
+ },
+ {
+ "page": "Example/F0307/Q.1.2",
+ "contents": "{{#ask: [[Category:F0307-Text]] |?Has text|+order=desc |format=table |link=none }}"
+ },
+ {
+ "page": "Example/F0307/Q.1.3",
+ "contents": "{{#ask: [[Category:F0307-Text]] |?Has text|+order=n-asc |format=table |link=none }}"
+ },
+ {
+ "page": "Example/F0307/Q.1.4",
+ "contents": "{{#ask: [[Category:F0307-Text]] |?Has text|+order=n-desc |format=table |link=none }}"
+ },
+ {
+ "page": "Example/F0307/Q.2.1",
+ "contents": "{{#ask: [[Category:F0307-Number]] |?Has number|+order=asc |format=table |link=none }}"
+ },
+ {
+ "page": "Example/F0307/Q.2.2",
+ "contents": "{{#ask: [[Category:F0307-Number]] |?Has number|+order=desc |format=table |link=none }}"
+ },
+ {
+ "page": "Example/F0307/Q.2.3",
+ "contents": "{{#ask: [[Category:F0307-Number]] |?Has number|+order=n-asc |format=table |link=none }}"
+ },
+ {
+ "page": "Example/F0307/Q.2.4",
+ "contents": "{{#ask: [[Category:F0307-Number]] |?Has number|+order=n-desc |format=table |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 asc printout (SORT_LOCALE_STRING)",
+ "subject": "Example/F0307/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">1.4.4.8.3.1<br />1.4.4.8.3.10<br />1.4.4.8.3.1001<br />1.4.4.8.3.11<br />1.4.4.8.3.12<br />1.4.4.8.3.2<br />1.4.4.8.3.3<br />1.4.4.8.3.4<br />1.4.4.8.3.5<br />1.4.4.8.3.6<br />1.4.4.8.3.7<br />1.4.4.8.3.8<br />1.4.4.8.3.9</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 desc printout (SORT_LOCALE_STRING)",
+ "subject": "Example/F0307/Q.1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">1.4.4.8.3.9<br />1.4.4.8.3.8<br />1.4.4.8.3.7<br />1.4.4.8.3.6<br />1.4.4.8.3.5<br />1.4.4.8.3.4<br />1.4.4.8.3.3<br />1.4.4.8.3.2<br />1.4.4.8.3.12<br />1.4.4.8.3.11<br />1.4.4.8.3.1001<br />1.4.4.8.3.10<br />1.4.4.8.3.1</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 n-asc printout (SORT_NATURAL)",
+ "subject": "Example/F0307/Q.1.3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">1.4.4.8.3.1<br />1.4.4.8.3.2<br />1.4.4.8.3.3<br />1.4.4.8.3.4<br />1.4.4.8.3.5<br />1.4.4.8.3.6<br />1.4.4.8.3.7<br />1.4.4.8.3.8<br />1.4.4.8.3.9<br />1.4.4.8.3.10<br />1.4.4.8.3.11<br />1.4.4.8.3.12<br />1.4.4.8.3.1001</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 n-desc printout (SORT_NATURAL)",
+ "subject": "Example/F0307/Q.1.4",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">1.4.4.8.3.1001<br />1.4.4.8.3.12<br />1.4.4.8.3.11<br />1.4.4.8.3.10<br />1.4.4.8.3.9<br />1.4.4.8.3.8<br />1.4.4.8.3.7<br />1.4.4.8.3.6<br />1.4.4.8.3.5<br />1.4.4.8.3.4<br />1.4.4.8.3.3<br />1.4.4.8.3.2<br />1.4.4.8.3.1</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#4 asc printout (SORT_NUMERIC)",
+ "subject": "Example/F0307/Q.2.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"1\">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />1,001</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#5 desc printout (SORT_NUMERIC)",
+ "subject": "Example/F0307/Q.2.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"1001\">1,001<br />12<br />11<br />10<br />9<br />8<br />7<br />6<br />5<br />4<br />3<br />2<br />1</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#6 n-asc printout (SORT_NATURAL)",
+ "subject": "Example/F0307/Q.2.3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"1\">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />1,001</td>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#7 n-desc printout (SORT_NATURAL)",
+ "subject": "Example/F0307/Q.2.4",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-number smwtype_num\" data-sort-value=\"1001\">1,001<br />12<br />11<br />10<br />9<br />8<br />7<br />6<br />5<br />4<br />3<br />2<br />1</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0308.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0308.json
new file mode 100644
index 00000000..7b259e22
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0308.json
@@ -0,0 +1,93 @@
+{
+ "description": "Test `format=table` with DEFAULTSORT and subject,property sorting",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Is performer",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "F0308/A",
+ "contents": "[[Category:F0308]] {{DEFAULTSORT:F0308/A}} [[Is performer::August]]"
+ },
+ {
+ "page": "F0308/AB",
+ "contents": "[[Category:F0308]] {{DEFAULTSORT:F0308/A}} [[Is performer::September]]"
+ },
+ {
+ "page": "F0308/Q.1",
+ "contents": "{{#ask: [[Category:F0308]] |sort=,Is performer |order=asc,asc |format=table}}"
+ },
+ {
+ "page": "F0308/Q.2",
+ "contents": "{{#ask: [[Category:F0308]] |sort=,Is performer |order=asc,desc |format=table}}"
+ },
+ {
+ "page": "F0308/Q.3",
+ "contents": "{{#ask: [[Category:F0308]] |sort=,Is performer |order=desc,asc |format=table}}"
+ },
+ {
+ "page": "F0308/Q.4",
+ "contents": "{{#ask: [[Category:F0308]] |sort=,Is performer |order=desc,desc |format=table}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 ( ,Is performer | asc,asc)",
+ "subject": "F0308/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/A\">F0308/A</a></td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/AB\">F0308/AB</a></td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#1 ( ,Is performer | asc,desc)",
+ "subject": "F0308/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/AB\">F0308/AB</a></td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/A\">F0308/A</a></td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#2 ( ,Is performer | desc,asc)",
+ "subject": "F0308/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/A\">F0308/A</a></td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/AB\">F0308/AB</a></td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "format",
+ "about": "#3 ( ,Is performer | desc,desc)",
+ "subject": "F0308/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/AB\">F0308/AB</a></td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=.* title=\"F0308/A\">F0308/A</a></td></tr>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0401.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0401.json
new file mode 100644
index 00000000..8fa351da
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0401.json
@@ -0,0 +1,68 @@
+{
+ "description": "Test `format=list` output",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Foo",
+ "contents": "[[Has page property::ABC]]"
+ },
+ {
+ "page": "Bar",
+ "contents": "[[Has page property::ABC]]"
+ },
+ {
+ "page": "Baz",
+ "contents": "[[Has page property::ABC]]"
+ },
+ {
+ "page": "Quok",
+ "contents": "[[Has page property::ABC]]"
+ },
+ {
+ "page": "Quuz",
+ "contents": "[[Has page property::DEF]]"
+ },
+ {
+ "page": "Example/0401",
+ "contents": "{{#ask:[[Has page property::ABC]] |format=list}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser-html",
+ "about": "#0 Basic List format (structure)",
+ "subject": "Example/0401",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [ "span.list-format > span.smw-row > span.smw-field > span.smw-value > a[title]", 4 ]
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 Basic List format (order)",
+ "subject": "Example/0401",
+ "assert-output": {
+ "to-contain": [
+ "Bar.*Baz.*Foo.*Quok"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0402.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0402.json
new file mode 100644
index 00000000..187cabcc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0402.json
@@ -0,0 +1,540 @@
+{
+ "description": "Test `format=list` output",
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": true
+ },
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Version",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Developer",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Company",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Website",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "f-0402",
+ "contents": "<includeonly>{{{1}}}-{{{SomeMainlabel}}}; #userparam: {{{#userparam|}}}; #querycondition: {{#tag:nowiki|{{{#querycondition|}}}}}; #querylimit: {{{#querylimit|}}}; #resultoffset: {{{#resultoffset|}}}; #rowcount: {{{#rowcount|}}}; #rownumber: {{{#rownumber|}}}; Version: {{{2}}}-{{{Version}}}; Developer: {{{3}}}-{{{Developer}}}; Company: {{{4}}}-{{{Company}}}; Website: {{{5}}}-{{{Website}}};</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "f-0402/intro",
+ "contents": "<includeonly><span class='intro'>#userparam: {{{#userparam|}}}; #querycondition: {{#tag:nowiki|{{{#querycondition|}}}}}; #querylimit: {{{#querylimit|}}}; #resultoffset: {{{#resultoffset|}}}; #rowcount: {{{#rowcount|}}};</span></includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "f-0402/outro",
+ "contents": "<includeonly><span class='outro'>#userparam: {{{#userparam|}}}; #querycondition: {{#tag:nowiki|{{{#querycondition|}}}}}; #querylimit: {{{#querylimit|}}}; #resultoffset: {{{#resultoffset|}}}; #rowcount: {{{#rowcount|}}};</span></includeonly>"
+ },
+ {
+ "page": "f-0402/Asoka",
+ "contents": "[[Category:0402]][[Version::3.8]][[Developer::Shae Erley]][[Developer::Keeley Considine]][[Company::Edgewire]]"
+ },
+ {
+ "page": "f-0402/Bitwolf",
+ "contents": "[[Category:0402]][[Version::0.3.8]][[Developer::Nealy Dawes]][[Developer::Harmony Hadgraft]][[Company::Eadel]]"
+ },
+ {
+ "page": "f-0402/Domainer",
+ "contents": "[[Category:0402]][[Version::9.49]][[Developer::Maridel Murdoch]][[Developer::Wiatt Crowest]][[Developer::Lottie Cruz]][[Company::Skimia]][[Website::https://icio.us/vestibulum/rutrum/rutrum/neque.aspx]]"
+ },
+ {
+ "page": "f-0402/Home Ing",
+ "contents": "[[Category:0402]][[Version::5.0.8]][[Developer::Mimi Kemish]][[Company::Oyope]]"
+ },
+ {
+ "page": "f-0402/Lotstring",
+ "contents": "[[Category:0402]][[Version::1.5]][[Developer::Willamina Strete]][[Company::Riffwire]]"
+ },
+ {
+ "page": "f-0402/Prodder",
+ "contents": "[[Category:0402]][[Version::0.1.8]][[Developer::Nevsa Slavin]][[Company::Bluezoom]][[Website::http://yale.edu/luctus/tincidunt/nulla/mollis/molestie/lorem/quisque.js]]"
+ },
+ {
+ "page": "f-0402/Span",
+ "contents": "[[Category:0402]][[Version::2.19]][[Developer::Meredith Yakubowicz]][[Company::Devbug]]"
+ },
+ {
+ "page": "f-0402/Tin",
+ "contents": "[[Category:0402]][[Version::0.1.5]][[Developer::Jemmie Crutchley]][[Company::Rhyzio]]"
+ },
+ {
+ "page": "f-0402/Veribet",
+ "contents": "[[Category:0402]][[Version::0.89]][[Developer::Gaspar Truelock]][[Company::Gabspot]]"
+ },
+ {
+ "page": "f-0402/Zaam-Dox",
+ "contents": "[[Category:0402]][[Version::8.06]][[Developer::Lew Whittek]][[Company::Kayveo]]"
+ },
+ {
+ "page": "f-0402/Test-01",
+ "contents": "{{#ask:[[Category:0402]]}}"
+ },
+ {
+ "page": "f-0402/Test-02",
+ "contents": "{{#ask:[[Category:0402]]|format=list}}"
+ },
+ {
+ "page": "f-0402/Test-02.2",
+ "contents": "{{#ask:[[Category:0402]]|format=plainlist}}"
+ },
+ {
+ "page": "f-0402/Test-03",
+ "contents": "{{#ask:[[Category:0402]]|format=template}}"
+ },
+ {
+ "page": "f-0402/Test-04",
+ "contents": "{{#ask:[[Category:0402]]|format=ol}}"
+ },
+ {
+ "page": "f-0402/Test-05",
+ "contents": "{{#ask:[[Category:0402]]|format=ul}}"
+ },
+ {
+ "page": "f-0402/Test-06",
+ "contents": "{{#ask:[[Category:0402]]|format=list|?Version|?Developer|?Company|?Website|template=f-0402|sep=SEPARATOR|propsep=PSEP|valuesep=VSEP|searchlabel=|mainlabel=SomeMainlabel|userparam=SomeUserParam|offset=2|limit=5}}"
+ },
+ {
+ "page": "f-0402/Test-07",
+ "contents": "{{#ask:[[Category:0402]]|format=ol|?Version=|?Developer|?Company|?Website|template=f-0402|sep=SEPARATOR|propsep=PSEP|valuesep=VSEP|searchlabel=|mainlabel=SomeMainlabel|userparam=SomeUserParam|offset=2|limit=5|named args=yes}}"
+ },
+ {
+ "page": "f-0402/Test-08",
+ "contents": "{{#ask:[[Category:0402]]|format=list|?Version|?Developer|?Company|?Website|sep=SEPARATOR|propsep=PSEP|valuesep=VSEP}}"
+ },
+ {
+ "page": "f-0402/Test-09",
+ "contents": "{{#ask:[[Category:0402]]|format=ol|?Version|?Developer|?Company|?Website|sep=SEPARATOR|propsep=PSEP|valuesep=VSEP|offset=2|limit=5}}{{#ask:[[Category:0402]]|format=ul|?Version|?Developer|?Company|?Website|sep=SEPARATOR}}"
+ },
+ {
+ "page": "f-0402/Test-10",
+ "contents": "{{#ask:[[Category:0402]]|format=list|introtemplate=f-0402/intro|outrotemplate=f-0402/outro}}"
+ },
+ {
+ "page": "f-0402/Test-11",
+ "contents": "{{#ask:[[Category:0402]]|format=list|template=f-0402|introtemplate=f-0402/intro|outrotemplate=f-0402/outro|limit=8}}"
+ },
+ {
+ "page": "f-0402/Test-12",
+ "contents": "{{#ask:[[Category:0402]]|format=ol|?Company|introtemplate=f-0402/intro|outrotemplate=f-0402/outro}}"
+ },
+ {
+ "page": "f-0402/Test-13",
+ "contents": "{{#ask:[[Category:0402]]|format=ol|?Company|link=none|headers=show|searchlabel=}}"
+ },
+ {
+ "page": "f-0402/Test-14",
+ "contents": "{{#ask:[[Category:0402]]|format=ol|?Company|link=subject|headers=hide|searchlabel=}}"
+ },
+ {
+ "page": "f-0402/Test-15",
+ "contents": "{{#ask:[[Category:0402]]|format=ol|?Company|link=all|headers=plain|searchlabel=}}"
+ },
+ {
+ "page": "f-0402/Test-16",
+ "contents": "{{#ask:[[Category:0402]]|format=list|class=some-class}}"
+ },
+ {
+ "page": "f-0402/Test-17",
+ "contents": "{{#ask:[[Category:0402]]|format=plainlist|class=some-class}}"
+ },
+ {
+ "page": "f-0402/Test-18",
+ "contents": "{{#ask:[[Category:0402]]|format=ol|class=some-class}}"
+ },
+ {
+ "page": "f-0402/Test-19",
+ "contents": "{{#ask:[[Category:0402]]|format=ul|class=some-class}}"
+ }
+
+ ],
+ "tests": [
+ {
+ "type": "parser-html",
+ "about": "#1 Plainlist format is called as standard output",
+ "subject": "f-0402/Test-01",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ "a[title] ~ a[title]"
+ ],
+ "not-contain": [
+ ".smw-format",
+ ".list-format",
+ ".smw-row",
+ ".smw-field",
+ ".smw-value"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#2 List format is called when format=list",
+ "subject": "f-0402/Test-02",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [
+ "span.list-format > span.smw-row > span.smw-field > span.smw-value > a[title]",
+ 10
+ ]
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#2.2 Plainlist format is called when format=plainlist",
+ "subject": "f-0402/Test-02.2",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ "a[title] ~ a[title]"
+ ],
+ "not-contain": [
+ ".smw-format",
+ ".list-format",
+ ".smw-row",
+ ".smw-field",
+ ".smw-value"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#3 List format is called when format=template (but no actual template specified)",
+ "subject": "f-0402/Test-03",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [
+ "span.list-format > span.smw-row > span.smw-field > span.smw-value > a[title]",
+ 10
+ ]
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#4 Ol format is called when format=ol",
+ "subject": "f-0402/Test-04",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [
+ "ol.ol-format > li.smw-row > span.smw-field > span.smw-value > a[title]",
+ 10
+ ]
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#5 Ul format is called when format=ul",
+ "subject": "f-0402/Test-05",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [
+ "ul.ul-format > li.smw-row > span.smw-field > span.smw-value > a[title]",
+ 10
+ ]
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 List format with template specified (numbered args)",
+ "subject": "f-0402/Test-06",
+ "assert-output": {
+ "to-contain": [
+ "/(SEPARATOR.+?){4}/",
+ "VSEP", // just make sure there's a bunch of VSEPs, don't count
+ "#userparam: SomeUserParam;",
+ "#querycondition: [[Category:0402]];",
+ "#querylimit: 5;",
+ "#resultoffset: 2;",
+ "#rowcount: 10;",
+ "#rownumber: 3;",
+ "#rownumber: 7;",
+ "{{{SomeMainlabel}}}", // Named template params are not replaced
+ "{{{Version}}}",
+ "{{{Developer}}}",
+ "{{{Company}}}",
+ "{{{Website}}}"
+ ],
+ "not-contain": [
+ "/(SEPARATOR){10,}/",
+ "PSEP",
+ "#rownumber: 2;",
+ "#rownumber: 8;",
+ "smw-row", // no structure for list with templates
+ "smw-field",
+ "smw-value",
+ "{{{1}}}", // Numbered template params are replaced
+ "{{{2}}}",
+ "{{{3}}}",
+ "{{{4}}}",
+ "{{{5}}}"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 Ol format with template specified (named args)",
+ "subject": "f-0402/Test-07",
+ "assert-output": {
+ "to-contain": [
+ "VSEP", // just make sure there's a bunch of VSEPs, don't count
+ "#userparam: SomeUserParam;",
+ "#querycondition: [[Category:0402]];",
+ "#querylimit: 5;",
+ "#resultoffset: 2;",
+ "#rowcount: 10;",
+ "#rownumber: 3;",
+ "#rownumber: 7;",
+ "smw-row", // Templates are applied inside rows for ol with templates
+ "{{{1}}}", // Numbered template params are not replaced
+ "{{{Version}}}", // ...except if the label is empty
+ "{{{3}}}",
+ "{{{4}}}",
+ "{{{5}}}"
+ ],
+ "not-contain": [
+ "SEPARATOR",
+ "PSEP",
+ "#rownumber: 2;",
+ "#rownumber: 8;",
+ "smw-field", // no structure below row for ol with templates
+ "smw-value",
+ "{{{SomeMainlabel}}}", // Named template params are replaced
+ "{{{2}}}", // ...except if the label is empty
+ "{{{Developer}}}",
+ "{{{Company}}}",
+ "{{{Website}}}"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 List format with sep",
+ "subject": "f-0402/Test-08",
+ "assert-output": { // at least 18, but not 19 or more, i.e. exactly 18
+ "to-contain": [
+ "/(span>SEPARATOR<span.+?){9}/",
+ "PSEP",
+ "VSEP"
+ ],
+ "not-contain": [ "/(span>SEPARATOR<span.+?){10,}/" ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9.1 Ol & ul format without sep (even if specified)",
+ "subject": "f-0402/Test-09",
+ "assert-output": {
+ "to-contain": [
+ "PSEP",
+ "VSEP"
+ ],
+ "not-contain": [
+ "SEPARATOR"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#9.2 Ol format with offset",
+ "subject": "f-0402/Test-09",
+ "assert-output": {
+ "to-contain": [
+ "ol.ol-format[start=\"3\"]"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#10.1 List format with introtemplate and outrotemplate",
+ "subject": "f-0402/Test-10",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"intro\">#userparam:&#160;; #querycondition: [[Category:0402]]; #querylimit: 50; #resultoffset: 0; #rowcount: 10;</span>",
+ "<span class=\"outro\">#userparam:&#160;; #querycondition: [[Category:0402]]; #querylimit: 50; #resultoffset: 0; #rowcount: 10;</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#10.2 List format with introtemplate and outrotemplate",
+ "subject": "f-0402/Test-10",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [ "span.intro + span.smw-format", 1 ],
+ [ "span.smw-format + span.outro", 1 ]
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#11.1 Template format with introtemplate and outrotemplate",
+ "subject": "f-0402/Test-11",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"intro\">#userparam:&#160;; #querycondition: [[Category:0402]]; #querylimit: 8; #resultoffset: 0; #rowcount: 10;</span>",
+ "<span class=\"outro\">#userparam:&#160;; #querycondition: [[Category:0402]]; #querylimit: 8; #resultoffset: 0; #rowcount: 10;</span>"
+ ],
+ "not-contain": [
+ ";, <a" //No default list separator (, ) between template calls
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#11.2 Template format with introtemplate and outrotemplate",
+ "subject": "f-0402/Test-11",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [ "p > span.intro:first-child + a", 1 ],
+ [ "p > span.outro + span.smw-list-furtherresults:last-child", 1 ]
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#12.1 Ol format with introtemplate and outrotemplate",
+ "subject": "f-0402/Test-12",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"intro\">#userparam:&#160;; #querycondition: [[Category:0402]]; #querylimit: 50; #resultoffset: 0; #rowcount: 10;</span>",
+ "<span class=\"outro\">#userparam:&#160;; #querycondition: [[Category:0402]]; #querylimit: 50; #resultoffset: 0; #rowcount: 10;</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#12.2 (1.31-) Ol format with introtemplate and outrotemplate",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "f-0402/Test-12",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [ "span.intro + ol.smw-format", 1 ],
+ [ "ol.smw-format + span.outro", 1 ]
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#13",
+ "subject": "f-0402/Test-13",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [ "span.smw-field-label > a", 10 ] // headers = show
+ ],
+ "not-contain": [
+ "span.smw-value > a" // link = none
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#14",
+ "subject": "f-0402/Test-14",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [ "li.smw-row > span.smw-field:first-child > span.smw-value > a", 10 ] // link = subject
+ ],
+ "not-contain": [
+ "li.smw-row > span.smw-field:not(:first-child) > span.smw-value > a", // link = subject
+ "span.smw-field-label" // headers = hide
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#15",
+ "subject": "f-0402/Test-15",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ [ "li.smw-row > span.smw-field > span.smw-value > a", 20 ], // link = all
+ [ "span.smw-field-label", 10 ] // headers = plain
+ ],
+ "not-contain": [
+ "span.smw-field-label > a" // headers = plain
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#16 List format is called as standard output",
+ "subject": "f-0402/Test-16",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ "span.list-format.some-class"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#17 List format is called as standard output",
+ "subject": "f-0402/Test-17",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "not-contain": [
+ ".some-class"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#18 List format is called as standard output",
+ "subject": "f-0402/Test-18",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ "ol.ol-format.some-class"
+ ]
+ }
+ },
+ {
+ "type": "parser-html",
+ "about": "#19 List format is called as standard output",
+ "subject": "f-0402/Test-19",
+ "assert-output": {
+ "to-be-valid-html": true,
+ "to-contain": [
+ "ul.ul-format.some-class"
+ ]
+ }
+ }
+
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0801.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0801.json
new file mode 100644
index 00000000..8707defa
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0801.json
@@ -0,0 +1,247 @@
+{
+ "description": "Test `format=embedded` output",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasSomePageProperty",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has another property",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Format/Embedded/A/1",
+ "contents": "[[HasSomePageProperty::ABC]] {{#subobject:HasSomePageProperty=123}} [[Category:Embedded format/A]]"
+ },
+ {
+ "page": "Format/Embedded/A/2",
+ "contents": "[[HasSomePageProperty::DEF]] {{#subobject:HasSomePageProperty=456}} [[Category:Embedded format/A]]"
+ },
+ {
+ "page": "Format/Embedded/B/1",
+ "contents": "[[HasSomePageProperty::ABC]] {{#subobject:HasSomePageProperty=123}} [[Category:Embedded format/B]]"
+ },
+ {
+ "page": "Format/Embedded/B/2",
+ "contents": "[[HasSomePageProperty::DEF]] {{#subobject:HasSomePageProperty=456}} [[Category:Embedded format/B]]"
+ },
+ {
+ "page": "Format/Embedded/A",
+ "contents": "{{#ask:[[Category:Embedded format/A]] |format=embedded |link=none |headers=show |embedformat=h1 }}"
+ },
+ {
+ "page": "Format/Embedded/B",
+ "contents": "{{#ask:[[Category:Embedded format/B]] |format=count}} {{#ask:[[Category:Embedded format/B]] |format=embedded |link=none |headers=show |embedformat=h1 }}"
+ },
+ {
+ "page": "Format/Embedded/C",
+ "contents": "{{:Format/Embedded/A/1}}"
+ },
+ {
+ "page": "Format/Embedded/D",
+ "contents": "[[Has another property::A123]] {{#ask:[[Category:Embedded format/B]] |format=count}} {{#ask:[[Category:Embedded format/B]] [[!Format/Embedded/B]]|format=embedded |link=none |headers=show |embedformat=h1 }} {{#set:Has another property=ABCD}}"
+ },
+ {
+ "page": "Format/Embedded/E/1",
+ "contents": "{{#ask:[[Category:Embedded format/A]] |format=embedded |link=none |headers=show |embedformat=h1 }} {{#ask:[[Category:Embedded format/B]] |format=embedded |link=none |headers=show |embedformat=h1 }} [[Category:Embedded format/E]]"
+ },
+ {
+ "page": "Format/Embedded/E",
+ "contents": "{{#ask:[[Category:Embedded format/E]] |format=embedded |link=none |headers=show |embedformat=h1 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Format/Embedded/A",
+ "skip-on": {
+ "mw": [ ">1.30.x", "See #2966" ]
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ],
+ "propertyValues": [
+ "Format/Embedded/A#_QUERYc91dabd03c0f49de2dc535c5b099aa45"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<h1><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FA.2F1\">",
+ "<h1><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FA.2F2\">",
+ "ABC",
+ "DEF"
+ ],
+ "not-contain": [
+ "<h1><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FA\">.*selflink\">Format/Embedded/A.*</h1>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#0.x",
+ "subject": "Format/Embedded/A",
+ "skip-on": {
+ "mw": [ "<1.31", "See #2966" ]
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ],
+ "propertyValues": [
+ "Format/Embedded/A#_QUERYc91dabd03c0f49de2dc535c5b099aa45"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<h1><span id=\"Format/Embedded/A/1\"></span><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FA.2F1\">",
+ "<h1><span id=\"Format/Embedded/A/2\"></span><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FA.2F2\">",
+ "ABC",
+ "DEF"
+ ],
+ "not-contain": [
+ "<h1><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FA\">.*selflink\">Format/Embedded/A.*</h1>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Format/Embedded/B",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ],
+ "propertyValues": [
+ "Format/Embedded/B#_QUERY62dcea2c67d5ddb3d9304fc34b792da2",
+ "Format/Embedded/B#_QUERYe368d606dd919a1d87cb50f61cfff289"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<h1>.*<span class=\"mw-headline\" id=\"Format.2FEmbedded.2FB.2F1\">",
+ "<h1>.*<span class=\"mw-headline\" id=\"Format.2FEmbedded.2FB.2F2\">",
+ "ABC",
+ "DEF"
+ ],
+ "not-contain": [
+ "<h1><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FB\">.*selflink\">Format/Embedded/B.*</h1>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (manual embedded)",
+ "subject": "Format/Embedded/C",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_INST",
+ "_MDAT",
+ "_SKEY",
+ "_SOBJ",
+ "HasSomePageProperty"
+ ],
+ "propertyValues": [
+ "Embedded format/A",
+ "ABC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (ensure that annotations for the target page are not disabled, exclude embbeded query from [[!Format/Embedded/B]] otherwise we point to ourselves)",
+ "subject": "Format/Embedded/D",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK",
+ "Has_another_property"
+ ],
+ "propertyValues": [
+ "A123",
+ "ABCD"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<h1>.*<span class=\"mw-headline\" id=\"Format.2FEmbedded.2FB.2F1\">",
+ "<h1>.*<span class=\"mw-headline\" id=\"Format.2FEmbedded.2FB.2F2\">",
+ "A123",
+ "ABC",
+ "DEF"
+ ],
+ "not-contain": [
+ "<h1><span class=\"mw-headline\" id=\"Format.2FEmbedded.2FD\">.*selflink\">Format/Embedded/D.*</h1>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 embedded an #ask embbeded page",
+ "subject": "Format/Embedded/E",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<a href=.* title=\"Format/Embedded/E/1\">Format/Embedded/E/1</a>",
+ "<a href=.* title=\"Format/Embedded/A/1\">Format/Embedded/A/1</a>",
+ "<a href=.* title=\"Format/Embedded/A/2\">Format/Embedded/A/2</a>",
+ "<a href=.* title=\"Format/Embedded/B/1\">Format/Embedded/B/1</a>",
+ "<a href=.* title=\"Format/Embedded/B/2\">Format/Embedded/B/2</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [ "_MDAT" ],
+ "smwgQueryResultCacheType": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0802.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0802.json
new file mode 100644
index 00000000..32cd398f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0802.json
@@ -0,0 +1,81 @@
+{
+ "description": "Test `format=template` [[SMW::on/off]] regression using `named args=yes` (#1453, skip-on 1.19)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has publication title",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has publication author",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/F0802/Cite publication/result format",
+ "contents": "<includeonly><div>{{{Author|}}}, <span>‘[[{{{Page|}}}|{{{Title|}}}]]’</span></div></includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/F0802/Cite publication",
+ "contents": "<includeonly>{{#ask: [[{{{1|}}}]] |?=Page |?Has publication author=Author |?Has publication title=Title |format=template |template=Example/F0802/Cite publication/result format|named args=yes |link=none }}</includeonly>"
+ },
+ {
+ "do-purge": true,
+ "page": "Example/F0802/A",
+ "contents": "{{#set: |Has publication title=Mitteilungen aus irischen Handschriften. V. Aus Egerton 1782. <em>DÅ«an in chÅicat cest inn</em>|Has publication author=Meyer (Kuno)}}"
+ },
+ {
+ "page": "Example/F0802/B",
+ "contents": "{{#set: |Has text=Extra text by #set: {{Example/F0802/Cite publication|Example/F0802/A }} }} {{#ask: [[Example/F0802/B]] |?Has text=Text |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/F0802/B",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK",
+ "Has_text"
+ ],
+ "propertyValues": []
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/F0802/A\">Mitteilungen aus irischen Handschriften. V. Aus Egerton 1782. <em>DÅ«an in chÅicat cest inn</em></a>’</span></div>",
+ "<td class=\"Text smwtype_txt\">Extra text by #set: <div>Meyer (Kuno), <span>‘"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [ "_MDAT" ],
+ "smwgQueryResultCacheType": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "mw-1.19.20": "<h1> contains an extra space"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0803.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0803.json
new file mode 100644
index 00000000..bd3e9002
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0803.json
@@ -0,0 +1,169 @@
+{
+ "description": "Test `format=template` with `sep`/`named args`/`template arguments` (#972, #2022, #2567)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/F0803/Sep",
+ "contents": "<includeonly>{{{Has text}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/F0803/Numbered",
+ "contents": "<includeonly>{{{1}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/F0803/Named",
+ "contents": "<includeonly>{{{Has text}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/F0803/NamedWithMainlabel",
+ "contents": "<includeonly>{{{main}}}{{{Has text}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/F0803/Legacy",
+ "contents": "<includeonly>{{{?Has text}}}</includeonly>"
+ },
+ {
+ "page": "Example/F0803/1",
+ "contents": "{{#subobject: |@category=F0803 |Has text=123 |Has text=456 }} {{#subobject: |@category=F0803 |Has text=abc }}"
+ },
+ {
+ "page": "Example/F0803/2",
+ "contents": "[[Category:F0803]][[Has text::foo\n=bar]]"
+ },
+ {
+ "page": "Example/F0803/Q.1",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/Sep |mainlabel=main |named args=yes |link=none |sep= &#32;&bull;&#32; |valuesep= &#32;&bull;&#32; <nowiki/>|sort=Has text |order=asc }}"
+ },
+ {
+ "page": "Example/F0803/Q.3",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/Legacy |mainlabel=main |named args=yes |link=none |sep= &#32;&bull;&#32; |valuesep= &#32;&bull;&#32; |sort=Has text |order=asc }}"
+ },
+ {
+ "page": "Example/F0803/Q.4",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/Named |mainlabel=main |named args=yes |link=none |sep= &#32;&bull;&#32; |valuesep= &#32;&bull;&#32; <nowiki/>|sort=Has text |order=asc }}"
+ },
+ {
+ "page": "Example/F0803/Q.5",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/NamedWithMainlabel |mainlabel=main |named args=yes |link=none |sep= &#32;&bull;&#32; |valuesep= &#32;&bull;&#32; <nowiki/>|sort=Has text |order=asc }}"
+ },
+ {
+ "page": "Example/F0803/Q.6",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/Numbered |mainlabel=main |named args=no |link=none |sep= &#32;&bull;&#32; |valuesep= &#32;&bull;&#32; |sort=Has text |order=asc }}"
+ },
+ {
+ "page": "Example/F0803/Q.7",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/Numbered |mainlabel=- |named args=no |link=none |sep= &#32;&bull;&#32; |valuesep= &#32;&bull;&#32; <nowiki/>|sort=Has text |order=asc }}"
+ },
+ {
+ "page": "Example/F0803/Q.8",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/Sep |mainlabel=main |named args=yes |link=none |sep= &#32;&bull;&#32; |sort=Has text |order=asc }}"
+ },
+ {
+ "page": "Example/F0803/Q.9",
+ "contents": "{{#ask: [[Category:F0803]] |?Has text |format=template |template=Example/F0803/Sep |named args=yes |sort=Has text |order=asc }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/F0803/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "123&#32;&#8226;&#32; 456&#32;&#8226;&#32;abc"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (template contains ?... )",
+ "subject": "Example/F0803/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "{{{?Has text}}}&#32;&#8226;&#32;{{{?Has text}}}"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (`named` selected)",
+ "subject": "Example/F0803/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "123&#32;&#8226;&#32; 456&#32;&#8226;&#32;abc"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (`named` selected with mainlabel)",
+ "subject": "Example/F0803/Q.5",
+ "assert-output": {
+ "to-contain": [
+ "Example/F0803/1#_a8833df1372ac8f410272cb680410853123&#32;&#8226;&#32; 456&#32;&#8226;&#32;Example/F0803/1#_41e021fb1955f0af8aa8b9dcb8313425abc"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (`numbered` selected)",
+ "subject": "Example/F0803/Q.6",
+ "assert-output": {
+ "to-contain": [
+ "Example/F0803/1#_a8833df1372ac8f410272cb680410853&#32;&#8226;&#32;Example/F0803/1#_41e021fb1955f0af8aa8b9dcb8313425"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (`numbered` selected, without mainlabel)",
+ "subject": "Example/F0803/Q.7",
+ "assert-output": {
+ "to-contain": [
+ "123&#32;&#8226;&#32; 456&#32;&#8226;&#32;abc"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 (`valuesep` parameter omitted)",
+ "subject": "Example/F0803/Q.8",
+ "assert-output": {
+ "to-contain": [
+ "123, 456&#32;&#8226;&#32;abc"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 (#2567)",
+ "subject": "Example/F0803/Q.9",
+ "assert-output": {
+ "to-contain": [
+ "123, 456abcfoo\n=bar"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [ "_MDAT" ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0804.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0804.json
new file mode 100644
index 00000000..1a0668b8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0804.json
@@ -0,0 +1,83 @@
+{
+ "description": "Test `format=embedded` with template transclution",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasSomePageProperty",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TmplP0804",
+ "contents": "<includeonly>[[Category:P0804]]</includeonly>"
+ },
+ {
+ "page": "Example/P0804/1",
+ "contents": "[[Category:P0804]]"
+ },
+ {
+ "page": "Example/P0804/2",
+ "contents": "{{TmplP0804}} [[Category:P0804/1]]"
+ },
+ {
+ "page": "Example/P0804/3",
+ "contents": "{{#ask:[[Category:P0804]] [[Category:P0804/1]] |format=embedded }} [[Category:P0804/3]]"
+ },
+ {
+ "page": "Example/P0804/Q.1",
+ "contents": "{{#ask:[[Category:P0804]] |format=embedded }}"
+ },
+ {
+ "page": "Example/P0804/Q.2",
+ "contents": "{{#ask:[[Category:P0804/3]] |format=embedded }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 only those with [[Category:P0804]] (exludes Example/P0804/3 as no class was imported)",
+ "subject": "Example/P0804/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"mw-headline\" id=\"Example.2FP0804.2F1\"><a href=.* title=\"Example/P0804/1\">Example/P0804/1</a></span>",
+ "<span class=\"mw-headline\" id=\"Example.2FP0804.2F2\"><a href=.* title=\"Example/P0804/2\">Example/P0804/2</a></span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 only those reachable via [[Category:P0804/3]] ",
+ "subject": "Example/P0804/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"mw-headline\" id=\"Example.2FP0804.2F3\"><a href=.* title=\"Example/P0804/3\">Example/P0804/3</a></span>",
+ "<span class=\"mw-headline\" id=\"Example.2FP0804.2F2\"><a href=.* title=\"Example/P0804/2\">Example/P0804/2</a></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [ "_MDAT" ],
+ "smwgQueryResultCacheType": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0805.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0805.json
new file mode 100644
index 00000000..55428e45
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/f-0805.json
@@ -0,0 +1,63 @@
+{
+ "description": "Test `format=template`, `format=plainlist` with `#show` and template args (#502)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Template/F0805_show_text",
+ "contents": "<includeonly>{{{Has text}}}</includeonly>"
+ },
+ {
+ "page": "Example/F0805/1",
+ "contents": "[[Has text::123]]"
+ },
+ {
+ "page": "Example/F0805/Q.1",
+ "contents": "{{#show: Example/F0805/1 |?Has text |format=template |named args=yes |template=Template/F0805_show_text }}"
+ },
+ {
+ "page": "Example/F0805/Q.2",
+ "contents": "{{#show: Example/F0805/1 |?Has text |format=plainlist |named args=yes |template=Template/F0805_show_text }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (#show, `format=template` to support template parameters)",
+ "subject": "Example/F0805/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "123"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (#show, `format=plainlist` to support template parameters)",
+ "subject": "Example/F0805/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "123"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0101.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0101.json
new file mode 100644
index 00000000..18d4bc79
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0101.json
@@ -0,0 +1,174 @@
+{
+ "description": "Test in-text annotation for use of restricted properties (#914, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "To-verify-annotation-works",
+ "contents": "[[Has date::1 Jan 1970]] {{#set:|Has date=1 Jan 1970}} {{#subobject:|Has date=1 Jan 1970}}"
+ },
+ {
+ "message-cache": "clear",
+ "page": "Modification-date",
+ "contents": "[[Modification date::1 Jan 1970]] {{#set:|Modification date=1 Jan 1970}} {{#subobject:|Modification date=1 Jan 1970}}"
+ },
+ {
+ "page": "Has-query",
+ "contents": "[[Has query::Invalid]] {{#set:|Has query=Invalid}} {{#subobject:|Has query=Invalid}}"
+ },
+ {
+ "page": "Has-subobject",
+ "contents": "[[Has subobject::Invalid]] {{#set:|Has subobject=Invalid}} {{#subobject:|Has subobject=Invalid}}"
+ },
+ {
+ "page": "Example/P0101/5",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0101/6",
+ "contents": "{{#set:|Has type=Page}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 verify that annotation/parser works",
+ "subject": "To-verify-annotation-works",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_date",
+ "_MDAT",
+ "_SKEY",
+ "_SOBJ"
+ ],
+ "propertyValues": [
+ "1970-01-01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "1 Jan 1970"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 verify no free annotation using Modification date (_MDAT) is created by the system",
+ "subject": "Modification-date",
+ "assert-store": {
+ "errors": [],
+ "semantic-data": {
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_SOBJ",
+ "_ERRC"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Property &quot;Modification date&quot; has a restricted application area and cannot be used as annotation property by a user."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 verify no free annotation using Has query",
+ "subject": "Has-query",
+ "assert-store": {
+ "semantic-data": {
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_SOBJ",
+ "_ERRC"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Property &quot;Has query&quot; has a restricted application area and cannot be used as annotation property by a user."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 verify no free annotation using Has subobject",
+ "subject": "Has-subobject",
+ "assert-store": {
+ "semantic-data": {
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_SOBJ",
+ "_ERRC"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Property &quot;Has subobject&quot; has a restricted application area and cannot be used as annotation property by a user."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 error on [[ ...]](NS_MAIN) with restricted declarative property",
+ "subject": "Example/P0101/5#_ERR20a1185193cbb57b6472d45844e0abbe",
+ "assert-store": {
+ "semantic-data": {
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRP",
+ "_ERRT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[8,\"smw-datavalue-property-restricted-declarative-use\",\"Has type\"]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 error on #set(NS_MAIN) with restricted declarative property",
+ "subject": "Example/P0101/6#_ERR20a1185193cbb57b6472d45844e0abbe",
+ "assert-store": {
+ "semantic-data": {
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRP",
+ "_ERRT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[8,\"smw-datavalue-property-restricted-declarative-use\",\"Has type\"]"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0102.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0102.json
new file mode 100644
index 00000000..02aef877
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0102.json
@@ -0,0 +1,258 @@
+{
+ "description": "Test in-text annotation on properties with invalid names/characters (#1567, #1638, #1727 `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has #",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0102/1",
+ "contents": "[[&#124; &#93;&#93;&lt;/td&gt;&lt;::123]]"
+ },
+ {
+ "page": "Example/P0102/2",
+ "contents": "[[<code>Has property a</code>::ABC]] {{#set: <code>Has property b</code>=DEF }}"
+ },
+ {
+ "page": "Example/P0102/3",
+ "contents": "[[<code>Has property e::ABC]] {{#set: <code>Has property f=DEF }}"
+ },
+ {
+ "page": "Example/P0102/4",
+ "contents": "[[File:[[Picture:: Foo.png ]]"
+ },
+ {
+ "page": "Example/P0102/Q3.1",
+ "contents": "{{#ask: [[<code>Has property e::ABC]] |link=none |format=table |sort=# |order=asc}}"
+ },
+ {
+ "page": "Example/P0102/5",
+ "contents": "[[<Foo>::abc]]"
+ },
+ {
+ "page": "Example/P0102/6",
+ "contents": "[[<Foo-<Bar>::abc]]"
+ },
+ {
+ "page": "Example/P0102/7",
+ "contents": "[[-<Foo>-<Bar>::abc]]"
+ },
+ {
+ "page": "Example/P0102/8",
+ "contents": "[[Foo-<Bar::abc]]"
+ },
+ {
+ "page": "Example/P0102/9",
+ "contents": "[[Foo-<Bar>::abc]]"
+ },
+ {
+ "page": "Example/P0102/10",
+ "contents": "[[Foo\nBar::abc]] [[Foo\rBar::123]] [[Foo\r\nBar::456]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 do not allow #",
+ "subject": "Example/P0102/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 strip tags",
+ "subject": "Example/P0102/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_property_a",
+ "Has_property_b",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "ABC",
+ "DEF"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 remove broken tags",
+ "subject": "Example/P0102/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_property_e",
+ "Has_property_f",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "ABC",
+ "DEF"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 allow things like sort=#",
+ "subject": "Example/P0102/Q3.1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 `[` to produce an error",
+ "subject": "Example/P0102/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 `<>` to produce an error",
+ "subject": "Example/P0102/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 `<>` to produce an error",
+ "subject": "Example/P0102/6",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 `<>` to produce an error",
+ "subject": "Example/P0102/7",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 to cut the name at `<`",
+ "subject": "Example/P0102/8",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Foo-",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 to cut the name at `<`",
+ "subject": "Example/P0102/9",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Foo-",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#10 (CR, LF are invalid)",
+ "subject": "Example/P0102/10",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_STRICT",
+ "SMW_PARSER_INL_ERROR",
+ "SMW_PARSER_HID_CATS"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0106.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0106.json
new file mode 100644
index 00000000..79f420ca
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0106.json
@@ -0,0 +1,67 @@
+{
+ "description": "Test #info parser output (#1019, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "message-cache": "clear",
+ "page": "P0106/Warning",
+ "contents": "{{#info: an warning text | warning }}"
+ },
+ {
+ "message-cache": "clear",
+ "page": "P0106/Error",
+ "contents": "{{#info: an error text | error }}"
+ },
+ {
+ "message-cache": "clear",
+ "page": "P0106/Note",
+ "contents": "{{#info: an info note | note }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "P0106/Warning",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"an warning text\">",
+ "<span class=\"smwtticon warning\">",
+ "<span class=\"smwttcontent\">an warning text</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "P0106/Error",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-highlighter\" data-type=\"5\" data-state=\"inline\" data-title=\"Error\" title=\"an error text\">",
+ "<span class=\"smwtticon error\">",
+ "<span class=\"smwttcontent\">an error text</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "P0106/Note",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-highlighter\" data-type=\"8\" data-state=\"inline\" data-title=\"Note\" title=\"an info note\">",
+ "<span class=\"smwtticon note\">",
+ "<span class=\"smwttcontent\">an info note</span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0107.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0107.json
new file mode 100644
index 00000000..19b4411c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0107.json
@@ -0,0 +1,145 @@
+{
+ "description": "Test #smwdoc parser output",
+ "setup": [
+ {
+ "page": "smwdoc-table",
+ "contents": "{{#smwdoc: table |parameters=base }}"
+ },
+ {
+ "page": "smwdoc-csv",
+ "contents": "{{#smwdoc: csv |parameters=all }}"
+ },
+ {
+ "page": "smwdoc-list",
+ "contents": "{{#smwdoc: list |parameters=all |language=de }}"
+ },
+ {
+ "page": "smwdoc-count",
+ "contents": "{{#smwdoc: count }}"
+ },
+ {
+ "page": "smwdoc-debug",
+ "contents": "{{#smwdoc: debug |parameters=specific |language=en }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (1.31-) (#1019)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "smwdoc-table",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"wikitable sortable\">",
+ "</td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#0 (1.31+) (#1019)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "smwdoc-table",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"wikitable sortable\">",
+ "</td></tr></tbody></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31-) (#1019)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "smwdoc-csv",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"wikitable sortable\">",
+ "</td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31+) (#1019)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "smwdoc-csv",
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"wikitable sortable\">",
+ "</td></tr></tbody></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31-) (#1019)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "smwdoc-list",
+ "assert-output": {
+ "to-contain": [
+ "</td>",
+ "<td>Legt fest, welche zusätzliche CSS-Klasse genutzt werden soll",
+ "</td></tr>",
+ "</td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31+) (#1019)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "smwdoc-list",
+ "assert-output": {
+ "to-contain": [
+ "</td>",
+ "<td>Legt fest, welche zusätzliche CSS-Klasse genutzt werden soll",
+ "</td></tr>",
+ "</td></tr></tbody></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (#3186)",
+ "subject": "smwdoc-count",
+ "assert-output": {
+ "to-contain": [
+ "This result format does not provide format specific parameters."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (#3186)",
+ "subject": "smwdoc-debug",
+ "assert-output": {
+ "to-contain": [
+ "This result format does not provide format specific parameters."
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0108.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0108.json
new file mode 100644
index 00000000..b2dd3058
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0108.json
@@ -0,0 +1,117 @@
+{
+ "description": "Test `#info`, `#ask` template output (#2347, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "P0108.Ask.Output",
+ "contents": "<includeonly>{{{1}}} {{{2}}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "P0108.Ask",
+ "contents": "<includeonly>{{#ask: [[Has page::P0108]] |?Has page |limit=1 |format=template |link=none |template=P0108.Ask.Output }}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "P0108",
+ "contents": "{{#info: message={{P0108.Ask}} }}"
+ },
+ {
+ "page": "Test/P0108/1",
+ "contents": "[[Has page::P0108]]"
+ },
+ {
+ "page": "Test/P0108/2",
+ "contents": "{{P0108}}"
+ },
+ {
+ "page": "Test/P0108/3",
+ "contents": "{{#set: Has text=Text with an [[Has page::annotation]] }}"
+ },
+ {
+ "page": "Test/P0108/4",
+ "contents": "{{#info: message={{#show: Test/P0108/3 |?Has text }} }}"
+ },
+ {
+ "page": "Test/P0108/5",
+ "contents": "{{#info: {{#show: Test/P0108/3 |?Has text }} }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #info with template generate output including encoded (&#91;) on/off marker",
+ "subject": "Test/P0108/2",
+ "skip-on": {
+ "mw-1.23.x": "works different in 1.23+"
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Test/P0108/1 P0108\">",
+ "<span class=\"smwttcontent\">Test/P0108/1 P0108</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 $info + #show (no annotation is leaked via a text element)",
+ "subject": "Test/P0108/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Text with an annotation\">"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 $info + #show (no annotation is leaked via a text element)",
+ "subject": "Test/P0108/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Text with an annotation\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0109.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0109.json
new file mode 100644
index 00000000..7f31bfc6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0109.json
@@ -0,0 +1,54 @@
+{
+ "description": "Test `#info`, `#ask`/`#show` with error output (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "page": "Test/P0109/1",
+ "contents": "Info: {{#info: message=Test some error {{#show: [[Test/P0109/2]] |?Has text }} }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (1.31-) switch #info to error display",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Test/P0109/1",
+ "assert-output": {
+ "to-contain": [
+ "Info: Test some error <span class=\"smw-highlighter\" data-type=\"4\""
+ ],
+ "not-contain": [
+ "Info: <span class=\"smw-highlighter\" data-type=\"5\"",
+ "<div class=\"smwttcontent\">Test some error <span class=\"smw-highlighter\" data-type=\"4\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#0 (1.31+) switch #info to error display",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Test/P0109/1",
+ "assert-output": {
+ "to-contain": [
+ "Info: Test some error </p><span class=\"smw-highlighter\" data-type=\"4\""
+ ],
+ "not-contain": [
+ "Info: <span class=\"smw-highlighter\" data-type=\"5\"",
+ "<div class=\"smwttcontent\">Test some error <span class=\"smw-highlighter\" data-type=\"4\""
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0110.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0110.json
new file mode 100644
index 00000000..56b1b16a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0110.json
@@ -0,0 +1,43 @@
+{
+ "description": "Test tooltip with error output on `_PVUC` (`smwgDVFeatures`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has Url",
+ "contents": "[[Has type::URL]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "page": "Test/P0110/1",
+ "contents": "[[Has Url::http://example.org/Foo]]"
+ },
+ {
+ "page": "Test/P0110/2",
+ "contents": "[[Has Url::http://example.org/Foo]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 error tooltip, title does not include <a> elements",
+ "subject": "Test/P0110/2",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property &quot;Has Url&quot; only permits unique value assignments and http://example.org/Foo",
+ "<span class=\"smwttcontent\">Property \"Has Url\" only permits unique value assignments and <i><a rel=\"nofollow\" class=\"external free\" href=\"http://example.org/Foo\">http://example.org/Foo</a></i>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgDVFeatures": [
+ "SMW_DV_PVUC"
+ ],
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0111.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0111.json
new file mode 100644
index 00000000..2a35981b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0111.json
@@ -0,0 +1,35 @@
+{
+ "description": "Test reserved property names",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Category",
+ "contents": "[[Has type::Page]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 reserved category name",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Category",
+ "assert-output": {
+ "onPageView": {},
+ "to-contain": [
+ "<div id=\"smw-property-name-reserved\" class=\"plainlinks smw-callout smw-callout-error\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0112.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0112.json
new file mode 100644
index 00000000..7f659c20
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0112.json
@@ -0,0 +1,58 @@
+{
+ "description": "Test #set_recurring_event parser (#3541, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "John Doe's Birthdays",
+ "contents": "{{#set_recurring_event: Is birthday |property=Has date |start=1948-11-03 |end=2019-01-06 |unit=year |period=1 }}"
+ },
+ {
+ "page": "John Doe's Number of Birthdays",
+ "contents": "{{#ask: [[Is birthday::John Doe's Birthdays]] |format=count }}"
+ },
+ {
+ "page": "Jane Doe's Birthdays",
+ "contents": "{{#set_recurring_event: Is birthday |property=Has date |start=1953-05-06 |unit=year |period=1 }}"
+ },
+ {
+ "page": "Jane Doe's Number of Birthdays",
+ "contents": "{{#ask: [[Is birthday::Jane Doe's Birthdays]] |format=count }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #set_recurring_event parser with end date",
+ "subject": "John Doe's Number of Birthdays",
+ "assert-output": {
+ "to-contain": [
+ "71"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 #set_recurring_event parser without end date",
+ "subject": "Jane Doe's Number of Birthdays",
+ "assert-output": {
+ "to-contain": [
+ "111"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDefaultNumRecurringEvents": "110"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0113.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0113.json
new file mode 100644
index 00000000..d6d39ce1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0113.json
@@ -0,0 +1,126 @@
+{
+ "description": "Test #set_recurring_event parser include and exclude parameters",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Team meetings - en",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=January 14, 2019 9:30 am |end=June 30, 2019 |unit=week |period=2 |include=May 7, 2019 9:30 am; June 18, 2019 9:30 am; June 27, 2019 10:00 am |exclude=May 6, 2019 9:30 am; June 17, 2019 9:30 am }}"
+ },
+ {
+ "page": "Team meetings - fr",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=14 janvier 2019 9:30 am |end=30 juin 2019 |unit=week |period=2 |include=7 mai 2019 9:30 am; 18 juin 2019 9:30 am; 27 juin 2019 10:00 am |exclude=6 mai 2019 9:30 am; 17 juin 2019 9:30 am }}"
+ },
+ {
+ "page": "Team meetings - ISO",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=2019-01-14T09:30:00 |end=2019-06-30 |unit=week |period=2 |include=2019-05-07T09:30:00; 2019-06-18T09:30:00; 2019-06-27T10:00:00 |exclude=2019-05-06T09:30:00; 2019-06-17T09:30:00 }}"
+ },
+ {
+ "page": "Team meetings in first half of 2019 - 0 - en",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - en]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in first half of 2019 - 1 - en",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - en]] |?Has date |format=plainlist }}"
+ },
+ {
+ "page": "Team meetings in first half of 2019 - 2 - fr",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - fr]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in first half of 2019 - 3 - fr",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - fr]] |?Has date |format=plainlist }}"
+ },
+ {
+ "page": "Team meetings in first half of 2019 - 4 - ISO",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - ISO]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in first half of 2019 - 5 - ISO",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - ISO]] |?Has date |format=plainlist }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #set_recurring_event parser with end date, included and excluded dates - count",
+ "subject": "Team meetings in first half of 2019 - 0 - en",
+ "assert-output": {
+ "to-contain": [
+ "13"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 #set_recurring_event parser with end date, included and excluded dates - print",
+ "subject": "Team meetings in first half of 2019 - 1 - en",
+ "assert-output": {
+ "to-contain": [
+ "27 juin 2019 10:00:00"
+ ],
+ "not-contain": [
+ "6 mai 2019 09:30:00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 #set_recurring_event parser with end date, included and excluded dates - count",
+ "subject": "Team meetings in first half of 2019 - 2 - fr",
+ "assert-output": {
+ "to-contain": [
+ "13"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #set_recurring_event parser with end date, included and excluded dates - print",
+ "subject": "Team meetings in first half of 2019 - 3 - fr",
+ "assert-output": {
+ "to-contain": [
+ "27 juin 2019 10:00:00"
+ ],
+ "not-contain": [
+ "6 mai 2019 09:30:00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 #set_recurring_event parser with end date, included and excluded dates - count",
+ "subject": "Team meetings in first half of 2019 - 4 - ISO",
+ "assert-output": {
+ "to-contain": [
+ "13"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 #set_recurring_event parser with end date, included and excluded dates - print",
+ "subject": "Team meetings in first half of 2019 - 5 - ISO",
+ "assert-output": {
+ "to-contain": [
+ "27 juin 2019 10:00:00"
+ ],
+ "not-contain": [
+ "6 mai 2019 09:30:00"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "fr",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0114.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0114.json
new file mode 100644
index 00000000..6921be44
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0114.json
@@ -0,0 +1,85 @@
+{
+ "description": "Test #set_recurring_event parser week number parameter",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Team meetings 1",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=January 15, 2019 9:30 am |end=December 31, 2019 |unit=month |week number=2 }}"
+ },
+ {
+ "page": "Team meetings 2",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=January 31, 2019 9:30 am |end=December 31, 2019 |unit=month |week number=-1 }}"
+ },
+ {
+ "page": "Team meetings in 2019 - 0",
+ "contents": "{{#ask: [[Is team meeting::Team meetings 1]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in 2019 - 1",
+ "contents": "{{#ask: [[Is team meeting::Team meetings 1]] |?Has date |format=plainlist }}"
+ },
+ {
+ "page": "Team meetings in 2019 - 2",
+ "contents": "{{#ask: [[Is team meeting::Team meetings 2]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in 2019 - 3",
+ "contents": "{{#ask: [[Is team meeting::Team meetings 2]] |?Has date |format=plainlist }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #set_recurring_event parser with end date and week number dates - count",
+ "subject": "Team meetings in 2019 - 0",
+ "assert-output": {
+ "to-contain": [
+ "12"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 #set_recurring_event parser with end date and week number dates - print",
+ "subject": "Team meetings in 2019 - 1",
+ "assert-output": {
+ "to-contain": [
+ "10 décembre 2019 09:30:00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 #set_recurring_event parser with end date and week number dates - count",
+ "subject": "Team meetings in 2019 - 2",
+ "assert-output": {
+ "to-contain": [
+ "12"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #set_recurring_event parser with end date and week number dates - print",
+ "subject": "Team meetings in 2019 - 3",
+ "assert-output": {
+ "to-contain": [
+ "29 août 2019 09:30:00"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "fr",
+ "wgLang": "de"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0115.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0115.json
new file mode 100644
index 00000000..96c9c8bd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0115.json
@@ -0,0 +1,130 @@
+{
+ "description": "Test `#set_recurring_event` parser for events on 29th to 31st of the month (#3598 - `wgContLang=fr`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Team meetings - en",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=January 31, 2003 9:30 am |end=December 31, 2004 9:30 am |unit=month }}"
+ },
+ {
+ "page": "Team meetings - fr",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=30 janvier 2003 9:30 am |end=31 décembre 2004 9:30 am |unit=month }}"
+ },
+ {
+ "page": "Team meetings - ISO",
+ "contents": "{{#set_recurring_event: Is team meeting |property=Has date |start=2003-01-29T09:30:00 |end=2004-12-31T09:30:00 |unit=month }}"
+ },
+ {
+ "page": "Team meetings in 2003 and 2004 - 0 - en",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - en]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in 2003 and 2004 - 1 - en",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - en]] |?Has date |format=plainlist }}"
+ },
+ {
+ "page": "Team meetings in 2003 and 2004 - 2 - fr",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - fr]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in 2003 and 2004 - 3 - fr",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - fr]] |?Has date |format=plainlist }}"
+ },
+ {
+ "page": "Team meetings in 2003 and 2004 - 4 - ISO",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - ISO]] |format=count }}"
+ },
+ {
+ "page": "Team meetings in 2003 and 2004 - 5 - ISO",
+ "contents": "{{#ask: [[Is team meeting::Team meetings - ISO]] |?Has date |format=plainlist }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #set_recurring_event parser for the 31st or alternatively the last day of a month - count",
+ "subject": "Team meetings in 2003 and 2004 - 0 - en",
+ "assert-output": {
+ "to-contain": [
+ "24"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 #set_recurring_event parser for the 31st or alternatively the last day of a month - print",
+ "subject": "Team meetings in 2003 and 2004 - 1 - en",
+ "assert-output": {
+ "to-contain": [
+ "31 mars 2003 09:30:00",
+ "30 avril 2003 09:30:00",
+ "30 novembre 2004 09:30:00",
+ "31 décembre 2004 09:30:00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 #set_recurring_event parser for the 30th or alternatively the last day of a month - count",
+ "subject": "Team meetings in 2003 and 2004 - 2 - fr",
+ "assert-output": {
+ "to-contain": [
+ "24"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #set_recurring_event parser for the 30th or alternatively the last day of a month - print",
+ "subject": "Team meetings in 2003 and 2004 - 3 - fr",
+ "assert-output": {
+ "to-contain": [
+ "28 février 2003 09:30:00",
+ "30 mars 2003 09:30:00",
+ "29 février 2004 09:30:00",
+ "30 mars 2004 09:30:00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 #set_recurring_event parser for the 29th or alternatively the last day of a month - count",
+ "subject": "Team meetings in 2003 and 2004 - 4 - ISO",
+ "assert-output": {
+ "to-contain": [
+ "24"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 #set_recurring_event parser for the 29th or alternatively the last day of a month - print",
+ "subject": "Team meetings in 2003 and 2004 - 5 - ISO",
+ "assert-output": {
+ "to-contain": [
+ "28 février 2003 09:30:00",
+ "29 août 2003 09:30:00",
+ "29 février 2004 09:30:00",
+ "29 août 2004 09:30:00"
+ ],
+ "not-contain": [
+ "29 février 2003 09:30:00",
+ "28 février 2004 09:30:00"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "fr",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0202.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0202.json
new file mode 100644
index 00000000..fa6e8ef2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0202.json
@@ -0,0 +1,84 @@
+{
+ "description": "Test #set parser to use template for output (#1146, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "SetParserTemplateToCreateAskLink",
+ "contents": "<includeonly>{{#ask: [[{{{property}}}::{{{value}}}]]|limit=0|searchlabel={{{value}}}|format=list }}</includeonly>"
+ },
+ {
+ "page": "Transclude-Template-Using-Set",
+ "contents": "{{#set:SetParserTemplateProperty=SetParserTemplateValue|+sep=;|template=SetParserTemplateToCreateAskLink}}"
+ },
+ {
+ "page": "Try-To-Transclude-Template-For-Invalid-PropertyValue",
+ "contents": "{{#set:Has date=NoTemplateForInvalidValue|+sep=;|template=SetParserTemplateToCreateAskLink}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #set annotation/parser with template",
+ "subject": "Transclude-Template-Using-Set",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY",
+ "SetParserTemplateProperty"
+ ],
+ "propertyValues": [
+ "SetParserTemplateValue"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 invalid property value declaration causes error",
+ "subject": "Try-To-Transclude-Template-For-Invalid-PropertyValue",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #ask link to be correctly parsed, #1146",
+ "subject": "Transclude-Template-Using-Set",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-list-furtherresults\">",
+ "Special:Ask/-5B-5BSetParserTemplateProperty::SetParserTemplateValue-5D-5D/mainlabel=/offset=0/format=list/searchlabel=SetParserTemplateValue\">SetParserTemplateValue</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0203.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0203.json
new file mode 100644
index 00000000..83e3367e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0203.json
@@ -0,0 +1,104 @@
+{
+ "description": "Test #set parser in combination with #subobject and template output (#1067, regression check)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Paragraph number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Paragraph",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Paragraph backlink",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "SimpleSetTemplate",
+ "contents": "<includeonly>Lorem ipsum.{{#set:Reference=Test}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "CreateParagraphAsSubobject",
+ "contents": "<includeonly><div style=\"display:none;\">{{#subobject:|Paragraph number={{{Paragraph number|}}}|Paragraph={{{Paragraph|}}}|Paragraph backlink={{PAGENAME}} }}</div></includeonly>"
+ },
+ {
+ "page": "Transclude-Template",
+ "contents": "{{CreateParagraphAsSubobject|Paragraph number=1|Paragraph=Test1 {{SimpleSetTemplate}} }} {{SimpleSetTemplate}}"
+ },
+ {
+ "page": "Ask-For-Transclude-Template",
+ "contents": "{{#ask:[[Paragraph backlink::Transclude-Template]]|?Paragraph}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Transclude-Template",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "Reference",
+ "_SOBJ"
+ ],
+ "propertyValues": [
+ "Test",
+ "Transclude-Template#_2d7f2b93bd6e9816ff85f022cddc62eb"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 subobject check",
+ "subject": "Transclude-Template#_2d7f2b93bd6e9816ff85f022cddc62eb",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Paragraph",
+ "Paragraph_backlink",
+ "Paragraph_number",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "1",
+ "Test1 Lorem ipsum.",
+ "Transclude-Template"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 check for the ask output",
+ "subject": "Ask-For-Transclude-Template",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Transclude-Template\">Transclude-Template</a>",
+ "<td class=\"Paragraph smwtype_txt\">Test1 Lorem ipsum.</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0204.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0204.json
new file mode 100644
index 00000000..aa556f91
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0204.json
@@ -0,0 +1,54 @@
+{
+ "description": "Test #set parser to produce error output (#870, en, verify that #set calls do not affect each other with previous errors)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Set-number-with-error",
+ "contents": "{{#set:Has number=12}} {{#set:Has number=32a}} {{#set:Has number=66}} {{#set:Has number=88b}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 with error",
+ "subject": "Set-number-with-error",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_number",
+ "_ERRC",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ 12,
+ 66
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "&quot;a&quot; can not be assigned to a declared number type with value 32.",
+ "&quot;b&quot; can not be assigned to a declared number type with value 88."
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0205.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0205.json
new file mode 100644
index 00000000..d69dbf4e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0205.json
@@ -0,0 +1,87 @@
+{
+ "description": "Test #set/#ask recursive annotation support (#711, #1055, recursive annotation using import-annotation=true via template)",
+ "setup": [
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "AskTemplateToAddPropertyAnnotation",
+ "contents": "<includeonly>{{#set:|ByAskTemplateToSetProperty=1234}}</includeonly>"
+ },
+ {
+ "page": "Example/0205",
+ "contents": "{{#set:|TestPropertyByAskTemplate=TestValueByAskTemplate}}"
+ },
+ {
+ "page": "Example/0205/Ask/List",
+ "contents": "{{#ask:[[TestPropertyByAskTemplate::TestValueByAskTemplate]]|link=none|sep=|format=list|template=AskTemplateToAddPropertyAnnotation|import-annotation=true}}"
+ },
+ {
+ "page": "Example/0205/Ask/Embedded/1",
+ "contents": "{{#ask:[[TestPropertyByAskTemplate::TestValueByAskTemplate]]|link=none|sep=|format=embedded|import-annotation=false}}"
+ },
+ {
+ "page": "Example/0205/Ask/Embedded/2",
+ "contents": "{{#ask:[[ByAskTemplateToSetProperty::1234]]|link=none|sep=|format=embedded|import-annotation=false}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/0205/Ask/List",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY",
+ "ByAskTemplateToSetProperty"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 embbeded with disabled recursive parse support",
+ "subject": "Example/0205/Ask/Embedded/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 embbeded with disabled recursive parse support",
+ "subject": "Example/0205/Ask/Embedded/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0206.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0206.json
new file mode 100644
index 00000000..0ebac9fd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0206.json
@@ -0,0 +1,105 @@
+{
+ "description": "Test #show parser on inverse printrequest (#1222, #1223)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasWorkManifested",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasWorkManifestedAsText",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/0206/1",
+ "contents": "[[HasWorkManifested::ABC]] + {{#show:{{FULLPAGENAME}}|?-HasWorkManifested|link=none}} + {{#show:{{FULLPAGENAME}}|?HasWorkManifested|link=none}}"
+ },
+ {
+ "page": "Example/0206/2",
+ "contents": "[[HasWorkManifested::{{FULLPAGENAME}}]] + {{#show:{{FULLPAGENAME}}|?-HasWorkManifested|link=none}} + {{#show:{{FULLPAGENAME}}|?HasWorkManifested|link=none}}"
+ },
+ {
+ "page": "Example/0206/3",
+ "contents": "[[HasWorkManifestedAsText::{{FULLPAGENAME}}]] + {{#show:{{FULLPAGENAME}}|?-HasWorkManifestedAsText|link=none}} + {{#show:{{FULLPAGENAME}}|?HasWorkManifestedAsText|link=none}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 where inverse is unknown and not displayed",
+ "subject": "Example/0206/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY",
+ "HasWorkManifested"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">ABC</a> + + ABC"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 inverse pointing to itself",
+ "subject": "Example/0206/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY",
+ "HasWorkManifested"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">Example/0206/2.* + Example/0206/2 + Example/0206/2"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2, see #1222, inverse is not displayed compared to #1",
+ "subject": "Example/0206/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY",
+ "HasWorkManifestedAsText"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<p>Example/0206/3 + + Example/0206/3"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0207.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0207.json
new file mode 100644
index 00000000..331722a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0207.json
@@ -0,0 +1,89 @@
+{
+ "description": "Test that undeclared properties with references remain after a `rebuildData` run (#1216, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Test/P0207",
+ "contents": "{{#set:Has number=12}} {{#set:Undeclared property=abc}} [[Undeclared prop::P0207]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "Test/P0207/1",
+ "contents": "{{:Test/P0207}}"
+ }
+ ],
+ "beforeTest": {
+ "maintenance-run": {
+ "rebuildData": true
+ }
+ },
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 Rebuild + clear cache to verify that the disposer (#1216) didn't remove undeclared properties that still contain references",
+ "subject": "Test/P0207",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "Has_number",
+ "_ERRP",
+ "_SKEY",
+ "_MDAT",
+ "Undeclared_property",
+ "Undeclared_prop"
+ ],
+ "propertyValues": [
+ 12,
+ "Abc",
+ "P0207"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 embedded page on disabled namespace",
+ "namespace": "NS_HELP",
+ "subject": "Test/P0207/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 0
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<a href=\".* title=\"P0207.*\">P0207</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_HELP": false,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0208.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0208.json
new file mode 100644
index 00000000..2e42ef6c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0208.json
@@ -0,0 +1,236 @@
+{
+ "description": "Test `#set` for various `_num` values without explicit precision (3 digit implicit), with/without leading zero, different printouts, negative numbers (#753, en, `smwgMaxNonExpNumber`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Example/P0208/1",
+ "contents": "{{#set:Has number=10000;2000;300;40;0;0.1;0.01;0.001;0.0001;0.02;0.003;0.0004;0.00005;4,297.31 e7|+sep=; }}"
+ },
+ {
+ "page": "Example/P0208/2",
+ "contents": "{{#set:Has number=.1;.01;.001;.00001;4.0e-4;.2e-5;.3e5|+sep=; }}"
+ },
+ {
+ "page": "Example/P0208/3",
+ "contents": "{{#set:Has number=-.1;-0.2;-.2e-5;-.3e5|+sep=; }}"
+ },
+ {
+ "page": "Example/P0208/1/1",
+ "contents": "{{#ask: [[Example/P0208/1]] |?Has number |format=table }}"
+ },
+ {
+ "page": "Example/P0208/1/2",
+ "contents": "{{#ask: [[Example/P0208/1]] |?Has number# |format=table }}"
+ },
+ {
+ "page": "Example/P0208/2/1",
+ "contents": "{{#ask: [[Example/P0208/2]] |?Has number |format=table }}"
+ },
+ {
+ "page": "Example/P0208/2/2",
+ "contents": "{{#ask: [[Example/P0208/2]] |?Has number# |format=table }}"
+ },
+ {
+ "page": "Example/P0208/3/1",
+ "contents": "{{#ask: [[Example/P0208/3]] |?Has number |format=table }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0208/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_number",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2,000",
+ "10,000",
+ "300",
+ "40",
+ "0",
+ "0.1",
+ "0.01",
+ "0.001",
+ "1.0e-4",
+ "0.02",
+ "0.003",
+ "4.0e-4",
+ "5.0e-5",
+ "42,973,100,000"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0208/2",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_number",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "0.1",
+ "0.01",
+ "0.001",
+ "1.0e-5",
+ "4.0e-4",
+ "2.0e-6",
+ "30000"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 #ask number output",
+ "subject": "Example/P0208/1/1",
+ "assert-output": {
+ "to-contain": [
+ "2,000",
+ "10,000",
+ "300",
+ "40",
+ "0",
+ "0.1",
+ "0.01",
+ "0.001",
+ "1.0e-4",
+ "0.02",
+ "0.003",
+ "4.0e-4",
+ "5.0e-5",
+ "42,973,100,000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #ask plain number output",
+ "subject": "Example/P0208/1/2",
+ "assert-output": {
+ "to-contain": [
+ "2000",
+ "10000",
+ "300",
+ "40",
+ "0",
+ "0.1",
+ "0.01",
+ "0.001",
+ "0.0001",
+ "0.02",
+ "0.003",
+ "0.0004",
+ "5.0e-5",
+ "42973100000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 #ask number output (non leading zero)",
+ "subject": "Example/P0208/2/1",
+ "assert-output": {
+ "to-contain": [
+ "0.1",
+ "0.01",
+ "0.001",
+ "1.0e-5",
+ "4.0e-4",
+ "2.0e-6",
+ "30,000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 #ask plain number output (non leading zero)",
+ "subject": "Example/P0208/2/2",
+ "assert-output": {
+ "to-contain": [
+ "0.1",
+ "0.01",
+ "0.001",
+ "1.0e-5",
+ "0.0004",
+ "2.0e-6",
+ "30000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 on negative use",
+ "subject": "Example/P0208/3",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_number",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "-30000",
+ "-2.0e-6",
+ "-0.2",
+ "-0.1"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 #ask on negative number output",
+ "subject": "Example/P0208/3/1",
+ "assert-output": {
+ "to-contain": [
+ "-30,000",
+ "-2.0e-6",
+ "-0.2",
+ "-0.1"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgMaxNonExpNumber": 1.0e+15,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0209.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0209.json
new file mode 100644
index 00000000..94c90d46
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0209.json
@@ -0,0 +1,247 @@
+{
+ "description": "Test `#set` for various `_qty` values without explicit precision (3 digit implicit), with/without leading zero, and different printouts (#753, en, `smwgMaxNonExpNumber`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]] [[Corresponds to::0.38610 sq mi, sqmi]] [[Corresponds to::1000 m²]] [[Corresponds to::247.1054 acre]] [[Corresponds to::988.42155 rood]]"
+ },
+ {
+ "page": "Example/P0209/1",
+ "contents": "{{#set: Has area=25 sq mi;30 sqmi; 10 m ²|+sep=; }}"
+ },
+ {
+ "page": "Example/P0209/2",
+ "contents": "{{#set:Has area=.25 sq mi;.30 sqmi; .10 m ²|+sep=; }}"
+ },
+ {
+ "page": "Example/P0209/1/1",
+ "contents": "{{#ask: [[Example/P0209/1]] |?Has area|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/1/2",
+ "contents": "{{#ask: [[Example/P0209/1]] |?Has area#|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/1/3",
+ "contents": "{{#ask: [[Example/P0209/1]] |?Has area#-n|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/1/4",
+ "contents": "{{#ask: [[Example/P0209/1]] |?Has area#-u|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/1/5",
+ "contents": "{{#ask: [[Example/P0209/1]] |?Has area#m²|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/2/1",
+ "contents": "{{#ask: [[Example/P0209/2]] |?Has area|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/2/2",
+ "contents": "{{#ask: [[Example/P0209/2]] |?Has area#|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/2/3",
+ "contents": "{{#ask: [[Example/P0209/2]] |?Has area#-n|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/2/4",
+ "contents": "{{#ask: [[Example/P0209/2]] |?Has area#-u|+order=desc |format=table }}"
+ },
+ {
+ "page": "Example/P0209/2/5",
+ "contents": "{{#ask: [[Example/P0209/2]] |?Has area#m²|+order=desc |format=table }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0209/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_area",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "64.750064750065",
+ "77.700077700078",
+ "0.01"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0209/2",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_area",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "0.64750064750065",
+ "0.77700077700078",
+ "0.0001"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 #ask quantity standard output",
+ "subject": "Example/P0209/1/1",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"77.700077700078\"",
+ "<span class=\"smwtext\">64.75&#160;km²</span>",
+ "25&#160;sqmi",
+ "64,750.065&#160;m²",
+ "16,000.091&#160;acre",
+ "64,000.359&#160;rood",
+ "<span class=\"smwtext\">77.7&#160;km²</span>",
+ "77,700.078&#160;m²",
+ "19,200.109&#160;acre",
+ "76,800.431&#160;rood",
+ "<span class=\"smwtext\">0.01&#160;km²</span>",
+ "0.00386&#160;sqmi",
+ "10&#160;m²",
+ "2.471&#160;acre",
+ "9.884&#160;rood"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #ask quantity plain output",
+ "subject": "Example/P0209/1/2",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"77.700077700078\"",
+ "64.750064750065 km²",
+ "77.700077700078 km²",
+ "0.01 km²"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 #ask quantity no unit output",
+ "subject": "Example/P0209/1/3",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"77.700077700078\"",
+ "77.700077700078<br />",
+ "<br />64.750064750065<br />",
+ "<br />0.01"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 #ask quantity only unit output",
+ "subject": "Example/P0209/1/4",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"77.700077700078\"",
+ "<br />km²<br />"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 #ask quantity output specific unit",
+ "subject": "Example/P0209/1/5",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"77.700077700078\"",
+ "<span class=\"smwtext\">64,750.065&#160;m²</span>",
+ "<span class=\"smwtext\">77,700.078&#160;m²</span>",
+ "<span class=\"smwtext\">10&#160;m²</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 #ask quantity standard output",
+ "subject": "Example/P0209/2/1",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"0.77700077700078\"",
+ "<span class=\"smwtext\">0.648&#160;km²</span>",
+ "<span class=\"smwtext\">0.777&#160;km²</span>",
+ "<span class=\"smwtext\">1.0e-4&#160;km²</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 #ask quantity plain unit output",
+ "subject": "Example/P0209/2/2",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"0.77700077700078\"",
+ "0.77700077700078 km²<br />",
+ "<br />0.64750064750065 km²<br />",
+ "<br />0.0001 km²"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 #ask quantity number only output",
+ "subject": "Example/P0209/2/3",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"0.77700077700078\"",
+ "0.77700077700078<br />",
+ "<br />0.64750064750065<br />",
+ "<br />0.0001"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#10 #ask quantity output specific unit",
+ "subject": "Example/P0209/2/5",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"0.77700077700078\"",
+ "<span class=\"smwtext\">647.501&#160;m²</span>",
+ "<span class=\"smwtext\">777.001&#160;m²</span>",
+ "<span class=\"smwtext\">0.1&#160;m²</span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgMaxNonExpNumber": 1.0e+15,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0210.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0210.json
new file mode 100644
index 00000000..4cc0fcaf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0210.json
@@ -0,0 +1,90 @@
+{
+ "description": "Test `#set_recurring_event` (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0210/1",
+ "contents": "{{#set_recurring_event:property=Has date |start=01 Feb 1970 |Has title=Recurring event |unit=year |period=12 |limit=3 }}"
+ },
+ {
+ "page": "Example/P0210/Q1",
+ "contents": "{{#ask: [[Has title::Recurring event]] |?Has date |format=table |link=none }}"
+ },
+ {
+ "page": "Example/P0210/2",
+ "contents": "{{#set_recurring_event:property=Has date |start=01 Feb 1970 |Has title=Recurring event 2 |unit=month |period=1 |limit=2 }} {{#set_recurring_event:property=Has date |start=01 Feb 1970 |Has title=Recurring event 2, Test|+sep=, |unit=month |period=1 |limit=2 }}"
+ },
+ {
+ "page": "Example/P0210/2",
+ "contents": "{{#set_recurring_event:property=Has date |start=01 Feb 1970 |Has title=Recurring event 2, Test|+sep=, |unit=month |period=1 |limit=2 }}"
+ },
+ {
+ "page": "Example/P0210/Q.2",
+ "contents": "{{#ask: [[Has title::Recurring event 2]] |?Has date |format=table |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0210/Q1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0210/1#_6c0c58959b4717205b4c1b2c3b0e3e84</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2440618.5\">1 February 1970</td>",
+ "<td class=\"smwtype_wpg\">Example/P0210/1#_999d559e938eeaee07f5f52de53638e9</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2445001.5\">1 February 1982</td>",
+ "<td class=\"smwtype_wpg\">Example/P0210/1#_f42111f2b6af198c265ef2d8330b6a13</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2449384.5\">1 February 1994</td>",
+ "<td class=\"smwtype_wpg\">Example/P0210/1#_bdfba16fe62b82d1eadcb21054d8452b</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2453767.5\">1 February 2006</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (set and replace)",
+ "subject": "Example/P0210/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0210/2#_6af7f30c51558500a93d03f795738a61</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2440618.5\">1 February 1970</td>",
+ "<td class=\"smwtype_wpg\">Example/P0210/2#_6c8f1e0c1ab31ea31cfbc3d4fa44a173</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2440677.5\">1 April 1970</td>",
+ "<td class=\"smwtype_wpg\">Example/P0210/2#_dc90c230beae622cd7e0d87ea1a93b78</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2440646.5\">1 March 1970</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0210/2#_6af7f30c51558500a93d03f795738a61",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has title",
+ "Has date",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "1970-02-01",
+ "Recurring event 2 ",
+ "Test"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0211.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0211.json
new file mode 100644
index 00000000..2629e5fa
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0211.json
@@ -0,0 +1,97 @@
+{
+ "description": "Test `#set`/`#subobject` to import annotation via `@json` syntax (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0211/1",
+ "contents": {
+ "import-from": "/../Fixtures/p-0211.1.txt"
+ }
+ },
+ {
+ "page": "Example/P0211/2",
+ "contents": {
+ "import-from": "/../Fixtures/p-0211.2.txt"
+ }
+ },
+ {
+ "page": "Example/P0211/3",
+ "contents": {
+ "import-from": "/../Fixtures/p-0211.3.txt"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #subobject",
+ "subject": "Example/P0211/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SOBJ",
+ "_SKEY",
+ "_MDAT"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 #set",
+ "subject": "Example/P0211/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 10,
+ "propertyKeys": [
+ "Kind",
+ "_cod",
+ "IcdId",
+ "Label",
+ "Link",
+ "Superclasses",
+ "Subclasses",
+ "Id",
+ "_SKEY",
+ "_MDAT"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #set depth issue",
+ "subject": "Example/P0211/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_SKEY",
+ "_MDAT"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0212.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0212.json
new file mode 100644
index 00000000..6fb37578
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0212.json
@@ -0,0 +1,102 @@
+{
+ "description": "Test `@@@` in-text annotation syntax (#1855, #1875 `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]] {{#set: Has property description=Some text with a link to [http://example.org/ foo] and <li>stripped `li` in title element</li>@en}}"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "P106",
+ "contents": "[[Has type::Text]] [[Has preferred property label::occupation@en]] [[Has preferred property label::ì§ì—…@ko]] [[Has preferred property label::è·æ¥­@ja]] [[Has property description::人物ã®è·æ¥­ã€‚「専門分野ã€@ja]] [[Has property description::ëŒ€ìƒ ì¸ë¬¼ì˜ ì§ì—…@ko]]"
+ },
+ {
+ "page": "Example/P0212/1",
+ "contents": "[[Has date::@@@]]"
+ },
+ {
+ "page": "Example/P0212/2",
+ "contents": "[[Has date::@@@|With extra caption]]"
+ },
+ {
+ "page": "Example/P0212/3",
+ "contents": "[[P106::@@@ja]]"
+ },
+ {
+ "page": "Example/P0212/4",
+ "contents": "[[P106::@@@ko|WithCaption]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0212/1",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-highlighter\" data-type=\"1\" data-state=\"inline\" data-title=\"Property\" title=\"Some text with a link to foo and stripped `li` in title element&#10;\">",
+ "<span class=\"smwttcontent\">Some text with a link to <a rel=\"nofollow\" class=\"external text\" href=\"http://example.org/\">foo</a> and <li>stripped `li` in title element</li></span>",
+ "title=\"Property:Has date\">Has date</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0212/2",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-highlighter\" data-type=\"1\" data-state=\"inline\" data-title=\"Property\" title=\"Some text with a link to foo and stripped `li` in title element&#10;\">",
+ "<span class=\"smwttcontent\">Some text with a link to <a rel=\"nofollow\" class=\"external text\" href=\"http://example.org/\">foo</a> and <li>stripped `li` in title element</li></span>",
+ "title=\"Property:Has date\">With extra caption</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31-)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0212/3",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:P106\">è·æ¥­</a></span><span class=\"smwttcontent\">人物ã®è·æ¥­ã€‚「専門分野ã€</span></span>&#160;<span title=\"P106\"><sup>áµ–</sup>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31+)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0212/3",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:P106\">è·æ¥­</a></span><span class=\"smwttcontent\">人物ã®è·æ¥­ã€‚「専門分野ã€</span></span>&#160;<span title=\"P106\"><sup>áµ–</sup>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0212/4",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:P106\">WithCaption</a></span><span class=\"smwttcontent\">ëŒ€ìƒ ì¸ë¬¼ì˜ ì§ì—…</span></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0301.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0301.json
new file mode 100644
index 00000000..e23bfc11
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0301.json
@@ -0,0 +1,62 @@
+{
+ "description": "Test #subobject category annotation (#1172)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/0301/1",
+ "contents": "{{#subobject:|Has page={{PAGENAME}}|@category=ABC;123|+sep=;}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 #subobject with category annotation",
+ "subject": "Example/0301/1#_04284bb237a62f6648c369d713da3996",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_page",
+ "_SKEY",
+ "_INST"
+ ],
+ "propertyValues": [
+ "Example/0301/1",
+ "ABC",
+ "123"
+ ]
+ }
+ }
+ },
+ {
+ "type": "query",
+ "about": "#0 query with subobject category",
+ "condition": "[[Category:ABC]][[Has page::Example/0301/1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Example/0301/1#0##_04284bb237a62f6648c369d713da3996"
+ ],
+ "count": "1"
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0302.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0302.json
new file mode 100644
index 00000000..9573fe14
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0302.json
@@ -0,0 +1,106 @@
+{
+ "description": "Test #subobject parser to use invalid assignments and create `_ERRC` (#1299, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0302/1",
+ "contents": "{{#subobject:abc.name |@category=ABC;123|+sep=;}}"
+ },
+ {
+ "page": "Example/P0302/2",
+ "contents": "{{#subobject:|Modification date= 1 Jan 1970 }}"
+ },
+ {
+ "page": "Example/P0302/3",
+ "contents": "{{#subobject:|Date= InvalidValue }}"
+ },
+ {
+ "page": "Example/P0302/4",
+ "contents": "{{#set_recurring_event:some.foo|property=Has date |start=June 8, 2010 |unit=day |period=1 |limit=10 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 dot scheme not permitted for user-defined named identifiers",
+ "subject": "Example/P0302/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 restricted property",
+ "subject": "Example/P0302/2#_6bcfd8f29c79e61086605597e7f2a8d4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "_ERRC",
+ "_SKEY"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 invalid value",
+ "subject": "Example/P0302/3#_d22883317b11ebaf00a39aaffc1d30fa",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "_ERRC",
+ "_SKEY"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 recurring events invalid name",
+ "subject": "Example/P0302/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRC",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": []
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0303.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0303.json
new file mode 100644
index 00000000..4dfbc0d0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0303.json
@@ -0,0 +1,70 @@
+{
+ "description": "Test `#subobject` and `#set` parser on values with spaces (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has effect",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0303/1",
+ "contents": {
+ "import-from": "/../Fixtures/p-0303.txt"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 values are trimmed (no leading spaces)",
+ "subject": "Example/P0303/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_effect",
+ "_SKEY",
+ "_MDAT",
+ "_SOBJ"
+ ],
+ "propertyValues": [
+ "Foo",
+ "Bar"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 values are trimmed (no leading spaces)",
+ "subject": "Example/P0303/1#_4cf77c0a97795d2717d53fa6165a0bf5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "Has_effect",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "Foo",
+ "Bar"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0401.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0401.json
new file mode 100644
index 00000000..6193813d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0401.json
@@ -0,0 +1,153 @@
+{
+ "description": "Test annotations with disabled capital links (#673, `wgCapitalLinks=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "has number",
+ "contents": "[[has type::number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "wikidata id",
+ "contents": "[[has type::string]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "founded",
+ "contents": "[[has type::date]] [[wikidata id::P571]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "set-non-capital-property",
+ "contents": "{{#set:|has type=boolean}} [[Category:Foo]]"
+ },
+ {
+ "page": "Empty",
+ "contents": "no annotation"
+ },
+ {
+ "page": "Single-category",
+ "contents": "[[Category:Foo]]"
+ },
+ {
+ "page": "Default-sort-with-non-capital-property",
+ "contents": "{{DEFAULTSORTKEY:Bar}} [[has number::42]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Empty",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "Empty"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Single-category",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_INST",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "Single-category",
+ "Foo"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Default-sort-with-non-capital-property",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "has_number"
+ ],
+ "propertyValues": [
+ "Bar",
+ 42
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 check has type despite wgCapitalLinks setting",
+ "subject": "set-non-capital-property",
+ "namespace": "SMW_NS_PROPERTY",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_TYPE",
+ "_INST"
+ ],
+ "propertyValues": [
+ "Boolean",
+ "Foo"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 check has type despite wgCapitalLinks setting, user-defined property is kept lower case",
+ "subject": "founded",
+ "namespace": "SMW_NS_PROPERTY",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_TYPE",
+ "wikidata id"
+ ],
+ "propertyValues": [
+ "P571"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgCapitalLinks": false,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0402.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0402.json
new file mode 100644
index 00000000..dc98bfde
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0402.json
@@ -0,0 +1,239 @@
+{
+ "description": "Test in-text parsing for double colon annotation such as `::::` or `:::` (#1066, #1075, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Double-single-colon",
+ "contents": "[[Has page:::Page/::Foo:Bar]] [[Has text:::Text/::Foo:Bar]] [[Has url::http://example.org/::Foo:Bar]]"
+ },
+ {
+ "page": "Double-double-colon",
+ "contents": "//::Page/::Foo:Bar is not allowed as title; [[Has text::::Text/::Foo:Bar]] [[Has url::http://example.org/:::Foo:Bar]]"
+ },
+ {
+ "page": "Example/P0402/3",
+ "contents": "[[Has date:::1 Jan 1970]]"
+ },
+ {
+ "page": "Number-error",
+ "contents": "[[Has number:::123]]"
+ },
+ {
+ "page": "Page-no-error",
+ "contents": "[[Has page:::123|abc]] [[Has page:::xyz]]"
+ },
+ {
+ "page": "Page-error",
+ "contents": "[[Has page::::123|abc]] [[Has page::::xyz]]"
+ },
+ {
+ "page": "Example/P0402/7",
+ "contents": "[[Has date::-901 AD]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Double-single-colon",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_page",
+ "Has_text",
+ "Has_url"
+ ],
+ "propertyValues": [
+ "Page/::Foo:Bar",
+ ":Text/::Foo:Bar",
+ "http://example.org/::Foo:Bar"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Page/::Foo:Bar",
+ "Text/::Foo:Bar",
+ "http://example.org/::Foo:Bar"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (: as leading text element to be converted to an indent)",
+ "subject": "Double-double-colon",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_text",
+ "Has_url"
+ ],
+ "propertyValues": [
+ "::Text/::Foo:Bar",
+ "http://example.org/:::Foo:Bar"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<dd>Text/::Foo:Bar",
+ "http://example.org/:::Foo:Bar"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Page-no-error",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_page"
+ ],
+ "propertyValues": [
+ "123",
+ "Xyz"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "abc",
+ "xyz"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Page-error",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "abc",
+ "&#58;&#58;xyz"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4",
+ "subject": "Example/P0402/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_date"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "1 Jan 1970"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5",
+ "subject": "Number-error",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "&#58;123"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 negative year with AD/CE era is not allowed",
+ "subject": "Example/P0402/7",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "&quot;-901 AD&quot; contains an extrinsic dash or other characters that are invalid for a date interpretation."
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0403.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0403.json
new file mode 100644
index 00000000..fd9af2cf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0403.json
@@ -0,0 +1,118 @@
+{
+ "description": "Test in-text annotations being disabled for when Factbox contains extra `[[ ... ]]` (#1126)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "SetValue",
+ "contents": "<includeonly>{{{value}}}</includeonly>"
+ },
+ {
+ "page": "Example/P0403/1",
+ "contents": "[[Has url::http://example.org/api.php?action=ask&query=%5B%5BModification%20date::%2B%5D%5D%7C%3FModification%20date%7Csort%3DModification%20date%7Corder%3Ddesc|api.php?action=ask&query=]] __SHOWFACTBOX__"
+ },
+ {
+ "page": "Example/P0403/2",
+ "contents": "{{#set:|Has text=ABC [[Has page::DEF]] 123|template=SetValue}}"
+ },
+ {
+ "page": "Example/P0403/3",
+ "contents": "{{#ask: [[Example/P0403/2]] |?Has text}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 don't expected to see a Modification date annotation due to %5B%5BModification%20date::%2B%5D%5D => [[Modification::+]]",
+ "subject": "Example/P0403/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_url"
+ ],
+ "propertyValues": [
+ "Example/P0403/1",
+ "http://example.org/api.php?action=ask&query=%5B%5BModification_date::%2B%5D%5D%7C%3FModification_date%7Csort%3DModification_date%7Corder%3Ddesc"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "http://example.org/api.php?action=ask&amp;query=%5B%5BModification_date::%2B%5D%5D%7C%3FModification_date%7Csort%3DModification_date%7Corder%3Ddesc\">api.php?action=ask&amp;query=</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1, refs #1314",
+ "subject": "Example/P0403/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_text",
+ "Has_page"
+ ],
+ "propertyValues": [
+ "Example/P0403/2",
+ "ABC [[Has page::DEF]] 123",
+ "DEF"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 does not contain any [[ :: ]] copied annotation values, refs #1314",
+ "subject": "Example/P0403/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ASK"
+ ],
+ "propertyValues": []
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "ABC DEF 123"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0404.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0404.json
new file mode 100644
index 00000000..e11b31e7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0404.json
@@ -0,0 +1,78 @@
+{
+ "description": "Test in-text annonation on different category colon identifier",
+ "setup": [
+ {
+ "page": "Example/P0404/1",
+ "contents": "[[Category:SingleColonNotion]], [[Category::DoubleColonNotion]]"
+ },
+ {
+ "page": "Example/P0404/2",
+ "contents": "[[Category:P4040]]"
+ },
+ {
+ "page": "Example/P0404/Q.1",
+ "contents": "{{#ask: [[Category:P4040]] |?Category }}"
+ },
+ {
+ "page": "Example/P0404/Q.2",
+ "contents": "{{#ask: [[Category:P4040]] |?Categories }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 : vs. ::",
+ "subject": "Example/P0404/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Category",
+ "_MDAT",
+ "_SKEY",
+ "_INST"
+ ],
+ "propertyValues": [
+ "SingleColonNotion",
+ "DoubleColonNotion"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (printrequest singular use)",
+ "subject": "Example/P0404/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"Category\"><a href=.*>Category</a></th>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0404/2\" title=\"Example/P0404/2\">Example/P0404/2</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (printrequest plural use)",
+ "subject": "Example/P0404/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"Category\"><a href=.*>Category</a></th>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0404/2\" title=\"Example/P0404/2\">Example/P0404/2</a></td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0405.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0405.json
new file mode 100644
index 00000000..c6935414
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0405.json
@@ -0,0 +1,212 @@
+{
+ "description": "Test in-text annotation via template and manual redirect (#895)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "UseTemplateForAnnotation",
+ "contents": "<includeonly>[[Has page::{{PAGENAME}}]], [[Has page::Abc]], {{#subobject:|Has page=123}}</includeonly>"
+ },
+ {
+ "page": "Page-with-template-for-unknown-redirect-target",
+ "contents": "{{UseTemplateForAnnotation}}"
+ },
+ {
+ "page": "Page-with-template-for-unknown-redirect-target",
+ "contents": "#REDIRECT [[To-be-unknown-template-redirect-target]]"
+ },
+ {
+ "page": "Page-with-template-for-known-redirect-target",
+ "contents": "{{UseTemplateForAnnotation}}"
+ },
+ {
+ "page": "To-be-known-template-redirect-target",
+ "contents": "{{UseTemplateForAnnotation}}"
+ },
+ {
+ "page": "Page-with-template-for-known-redirect-target",
+ "contents": "#REDIRECT [[To-be-known-template-redirect-target]]"
+ },
+ {
+ "page": "Page-with-annotation-for-unknown-redirect-target",
+ "contents": "[[Has page::{{PAGENAME}}]]"
+ },
+ {
+ "page": "Page-with-annotation-for-unknown-redirect-target",
+ "contents": "#REDIRECT [[To-be-unknown-redirect-target]]"
+ },
+ {
+ "page": "Page-with-template-was-redirected-now-restored",
+ "contents": "{{UseTemplateForAnnotation}}"
+ },
+ {
+ "page": "Page-with-template-was-redirected-now-restored",
+ "contents": "#REDIRECT [[To-be-unknown-temporary-redirect-target]]"
+ },
+ {
+ "page": "Page-with-template-was-redirected-now-restored",
+ "contents": "{{UseTemplateForAnnotation}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 verify redirect for unknown target",
+ "subject": "Page-with-template-for-unknown-redirect-target",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 1,
+ "propertyKeys": [
+ "_SKEY"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI"
+ ],
+ "propertyValues": [
+ "Page-with-template-for-unknown-redirect-target#0##"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 verify unknown target",
+ "subject": "To-be-unknown-template-redirect-target",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 1,
+ "propertyKeys": [
+ "_SKEY"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI"
+ ],
+ "propertyValues": [
+ "Page-with-template-for-unknown-redirect-target#0##"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 verify redirect for knwown target",
+ "subject": "Page-with-template-for-known-redirect-target",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_SOBJ",
+ "Has_page"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI",
+ "Has_page"
+ ],
+ "propertyValues": [
+ "Page-with-template-for-known-redirect-target#0##",
+ "To-be-known-template-redirect-target#0##"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 verify knwown target",
+ "subject": "To-be-known-template-redirect-target",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_SOBJ",
+ "Has_page"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI",
+ "Has_page"
+ ],
+ "propertyValues": [
+ "Page-with-template-for-known-redirect-target#0##",
+ "To-be-known-template-redirect-target#0##"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 verify redirect for unknown target",
+ "subject": "Page-with-annotation-for-unknown-redirect-target",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 1,
+ "propertyKeys": [
+ "_SKEY"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI"
+ ],
+ "propertyValues": [
+ "Page-with-annotation-for-unknown-redirect-target#0##"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 verify that a redirected page can be restored to host annotations",
+ "subject": "Page-with-template-was-redirected-now-restored",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_page",
+ "_SOBJ"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "Has_page"
+ ],
+ "propertyValues": [
+ "Page-with-template-was-redirected-now-restored#0##"
+ ]
+ }
+ }
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0406.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0406.json
new file mode 100644
index 00000000..218ca898
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0406.json
@@ -0,0 +1,60 @@
+{
+ "description": "Test in-text annotation for unrestricted template parse using `import-annotation=true` (#1055)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasUnrestrictedPage",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "CreateAnnotationViaAskTemplate",
+ "contents": "<includeonly>[[HasUnrestrictedPage::{{{1}}}]]</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "TemplateForUnrestrictedParse",
+ "contents": "<includeonly>{{#ask: [[HasUnrestrictedPage::{{{1}}}]]|?HasUnrestrictedPage|link=none|format=template|template=CreateAnnotationViaAskTemplate|import-annotation=true}}</includeonly>"
+ },
+ {
+ "page": "Page-with-annotation",
+ "contents": "[[HasUnrestrictedPage::SearchPageWithAnnotation]]"
+ },
+ {
+ "page": "Page-with-template",
+ "contents": "{{TemplateForUnrestrictedParse|SearchPageWithAnnotation}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Page-with-template",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "HasUnrestrictedPage",
+ "_MDAT",
+ "_ASK"
+ ],
+ "propertyValues": [
+ "Page-with-annotation"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0407.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0407.json
new file mode 100644
index 00000000..91e64556
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0407.json
@@ -0,0 +1,61 @@
+{
+ "description": "Test in-text annotation for a redirect that is pointing to a deleted target (#1105)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasPropertyForUse",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/0407/1",
+ "contents": "#REDIRECT [[Example/0407/2]]"
+ },
+ {
+ "do-delete": true,
+ "page": "Example/0407/2",
+ "contents": "[[HasPropertyForUse::ABC]]"
+ },
+ {
+ "page": "Example/0407/3",
+ "contents": "[[HasPropertyForUse::Example/0407/1]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 check annotation for a deleted redirected target subject",
+ "subject": "Example/0407/3",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "HasPropertyForUse"
+ ],
+ "propertyValues": [
+ "Example/0407/2"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0408.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0408.json
new file mode 100644
index 00000000..a39f1e03
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0408.json
@@ -0,0 +1,45 @@
+{
+ "description": "Test in-text annotation for multiple property assignment using non-strict parser mode (#1252, en)",
+ "setup": [
+ {
+ "page": "Example/P0408/1",
+ "contents": "[[Testproperty1::Testproperty2::200]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 disabled strict mode allows for multi property assignment",
+ "subject": "Example/P0408/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Testproperty1",
+ "Testproperty2",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "200"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgParserFeatures": [
+ "SMW_PARSER_NONE"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0409.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0409.json
new file mode 100644
index 00000000..86ceea5f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0409.json
@@ -0,0 +1,217 @@
+{
+ "description": "Test in-text annotation for `_rec`/`_mlt_rec` (+ subobject) for when record type points to another record type (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has monolingual text",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record one",
+ "contents": "[[Has type::Record]] [[Has fields::Has text;Has number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record two",
+ "contents": "[[Has type::Record]] [[Has fields::Has text;Has record one]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record one mlt",
+ "contents": "[[Has type::Record]] [[Has fields::Has monolingual text;Has number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record two mlt",
+ "contents": "[[Has type::Record]] [[Has fields::Has monolingual text;Has record one mlt]]"
+ },
+ {
+ "page": "Example/P0409/1/1",
+ "contents": "[[Has record two::Foo;abc\\;12]]"
+ },
+ {
+ "page": "Example/P0409/1/2",
+ "contents": "{{#subobject: |Has record two=Foo;abc\\;12 }}"
+ },
+ {
+ "page": "Example/P0409/2/1",
+ "contents": "[[Has record one mlt::test@en;42]]"
+ },
+ {
+ "page": "Example/P0409/2/2",
+ "contents": "{{#subobject: |Has record one mlt=test@en;42}}"
+ },
+ {
+ "page": "Example/P0409/3/1",
+ "contents": "[[Has record two mlt::one@en;two@fr\\;123]]"
+ },
+ {
+ "page": "Example/P0409/3/2",
+ "contents": "{{#subobject: |Has record two mlt=one@en;two@fr\\;123}}"
+ },
+ {
+ "page": "Example/P0409/3/2a",
+ "contents": "{{#ask: [[Has record two mlt::one@en;two@fr\\;123]] |?Has record two mlt}}"
+ },
+ {
+ "page": "Example/P0409/3/2b",
+ "contents": "{{#ask: [[Has record two mlt::one@en;two@fr\\;123]] |?Has record two mlt|+index=1 |?Has record two mlt|+index=2}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0409/1/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_record_two",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "Foo; abc\\; 12"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0409/1/2#_863c94681079337ad25674e3a7ce33e7",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "Has_record_two",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "Foo; abc\\; 12"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0409/2/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_record_one_mlt",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "test@en; 42"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0409/2/2#_aa886e35ba32dd0c6e43a026230362f4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "Has_record_one_mlt",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "test@en; 42"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4",
+ "subject": "Example/P0409/3/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_record_two_mlt",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "one@en; two@fr\\; 123"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5",
+ "subject": "Example/P0409/3/2#_4d3b4405d3a60255e63cde196092a367",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "Has_record_two_mlt",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "one@en; two@fr\\; 123"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (edge case that will probably never surface but we verify that the description can be decoded without failing the parser)",
+ "subject": "Example/P0409/3/2a",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0409/3/2#_4d3b4405d3a60255e63cde196092a367",
+ "<td class=\"Has-record-two-mlt smwtype_rec\">one (en) (two (fr) (123))</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 same as #6 (query condition is identical, printoutput is different)",
+ "subject": "Example/P0409/3/2b",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0409/3/2#_4d3b4405d3a60255e63cde196092a367",
+ "<td class=\"Has-record-two-mlt smwtype_mlt_rec\">one (en)</td>",
+ "<td class=\"Has-record-two-mlt smwtype_rec\">two (fr) (123)</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0410.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0410.json
new file mode 100644
index 00000000..b060badc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0410.json
@@ -0,0 +1,458 @@
+{
+ "description": "Test in-text annotation on `_num`/`_tem`/`_qty` type with denoted precision (`_PREC`) and/or `-p<num>` printout precision marker (#1335, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has temperature with prec4",
+ "contents": "[[Has type::Temperature]] [[Display precision of::4]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has temperature with prec2",
+ "contents": "[[Has type::Temperature]] [[Display precision of::2]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has temperature",
+ "contents": "[[Has type::Temperature]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number with prec4",
+ "contents": "[[Has type::Number]] [[Display precision of::4]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number with prec2",
+ "contents": "[[Has type::Number]] [[Display precision of::2]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]] [[Corresponds to::0.38610 sq mi]] [[Corresponds to::1000 m²]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area with prec4",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]] [[Corresponds to::0.38610 sq mi]] [[Corresponds to::1000 m²]] [[Display precision of::4]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area with prec2",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]] [[Corresponds to::0.38610 sq mi]] [[Corresponds to::1000 m²]] [[Display precision of::2]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area with prec0",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]] [[Corresponds to::0.38610 sq mi]] [[Corresponds to::1000 m²]] [[Display precision of::0]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has currency with prec2",
+ "contents": "[[Has type::Quantity]] [[Display units::€, ¥]] [[Corresponds to:: € 1.00]] [[Corresponds to::¥,JPY,Japanese Yen 114.2121]] [[Display precision of::2]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has currency with prec4",
+ "contents": "[[Has type::Quantity]] [[Display units::€, ¥]] [[Corresponds to:: € 1.00]] [[Corresponds to::¥,JPY,Japanese Yen 114.2121]] [[Display precision of::4]]"
+ },
+ {
+ "page": "Example/P0410/1",
+ "contents": "[[Has temperature with prec4::32 °F]] [[Has temperature with prec4::100 °C]]"
+ },
+ {
+ "page": "Example/P0410/2",
+ "contents": "[[Has temperature with prec2::32 °F]] [[Has temperature with prec2::100 °C]]"
+ },
+ {
+ "page": "Example/P0410/1/1",
+ "contents": "{{#ask: [[Has temperature with prec4::32 °F]] |?Has temperature with prec4 |+order=asc |format=table }}"
+ },
+ {
+ "page": "Example/P0410/2/1",
+ "contents": "{{#ask: [[Has temperature with prec2::32 °F]] |?Has temperature with prec2 |+order=asc |format=table }}"
+ },
+ {
+ "page": "Example/P0410/3/1",
+ "contents": "[[Has number with prec4::.001]] [[Has number with prec2::.001]] [[Has number::.003]]"
+ },
+ {
+ "page": "Example/P0410/3/2",
+ "contents": "[[Has number with prec4::.005]] [[Has number with prec2::.005]] [[Has number::.008]]"
+ },
+ {
+ "page": "Example/P0410/3/3",
+ "contents": "[[Has number with prec2::42]] [[Has number::42]]"
+ },
+ {
+ "page": "Example/P0410/3/4",
+ "contents": "[[Has number with prec2::10,000]] [[Has number::10,000]]"
+ },
+ {
+ "page": "Example/P0410/3",
+ "contents": "{{#ask: [[~Example/P0410/3/*]] |?Has number with prec4 |?Has number with prec2 |?Has number |format=table }}"
+ },
+ {
+ "page": "Example/P0410/4/1",
+ "contents": "[[Has area with prec2::10,000 m²]] [[Has area with prec4::0.02 km²]] [[Has area with prec0::3.33 km²]]"
+ },
+ {
+ "page": "Example/P0410/4",
+ "contents": "{{#ask: [[~Example/P0410/4/*]] |?Has area with prec4 |?Has area with prec2 |?Has area with prec0 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/5/1",
+ "contents": "[[Has currency with prec2::€ 5]] [[Has currency with prec4::¥ 100]]"
+ },
+ {
+ "page": "Example/P0410/5/2",
+ "contents": "[[Has currency with prec2::€ 5,000]] [[Has currency with prec4::¥ 0.50]]"
+ },
+ {
+ "page": "Example/P0410/5",
+ "contents": "{{#ask: [[~Example/P0410/5/*]] |?Has currency with prec4 |?Has currency with prec2 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/6/1",
+ "contents": "[[Has number::10,000]] [[Has number::.005]] [[Has number::42.005]] [[Has number::1001]]"
+ },
+ {
+ "page": "Example/P0410/6a",
+ "contents": "{{#ask: [[~Example/P0410/6/*]] |?Has number#-p2 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/6b",
+ "contents": "{{#ask: [[~Example/P0410/6/*]] |?Has number#-p4 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/6c",
+ "contents": "{{#ask: [[~Example/P0410/6/*]] |?Has number#-p3-n |format=table }}"
+ },
+ {
+ "page": "Example/P0410/7/1",
+ "contents": "[[Has area::10,000 m²]] [[Has area::0.02 km²]] [[Has area::3.33 km²]]"
+ },
+ {
+ "page": "Example/P0410/7a",
+ "contents": "{{#ask: [[~Example/P0410/7/*]] |?Has area#-p2 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/7b",
+ "contents": "{{#ask: [[~Example/P0410/7/*]] |?Has area#m²-p3 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/7c",
+ "contents": "{{#ask: [[~Example/P0410/7/*]] |?Has area#-n-p2 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/8/1",
+ "contents": "[[Has temperature::32 °F]] [[Has temperature::100 °C]]"
+ },
+ {
+ "page": "Example/P0410/8a",
+ "contents": "{{#ask: [[~Example/P0410/8/*]] |?Has temperature#-p2 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/8b",
+ "contents": "{{#ask: [[~Example/P0410/8/*]] |?Has temperature#°C-p3 |format=table }}"
+ },
+ {
+ "page": "Example/P0410/8c",
+ "contents": "{{#ask: [[~Example/P0410/8/*]] |?Has temperature#-n-p2 |format=table }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0410/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_temperature_with_prec4",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ 273.15,
+ 373.15
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0410/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_temperature_with_prec2",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ 273.15,
+ 373.15
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0410/1/1",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"273.15\"",
+ "<span class=\"smwtext\">273.1500&#160;K</span>",
+ "0.0000&#160;°C",
+ "32.0000&#160;°F",
+ "491.6700&#160;°R",
+ "<span class=\"smwtext\">373.1500&#160;K</span>",
+ "100.0000&#160;°C",
+ "212.0000&#160;°F",
+ "671.6700&#160;°R"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0410/2/1",
+ "assert-output": {
+ "to-contain": [
+ "data-sort-value=\"273.15\"",
+ "<span class=\"smwtext\">273.15&#160;K</span>",
+ "0.00&#160;°C",
+ "32.00&#160;°F",
+ "491.67&#160;°R",
+ "<span class=\"smwtext\">373.15&#160;K</span>",
+ "100.00&#160;°C",
+ "212.00&#160;°F",
+ "671.67&#160;°R"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 Prec2 vs Prec4 incl. rounding on output for plain number",
+ "subject": "Example/P0410/3",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-number-with-prec4 smwtype_num\" data-sort-value=\"0.001\">0.0010",
+ "class=\"Has-number-with-prec2 smwtype_num\" data-sort-value=\"0.001\">0.00",
+ "class=\"Has-number smwtype_num\" data-sort-value=\"0.003\">0.003",
+ "class=\"Has-number-with-prec4 smwtype_num\" data-sort-value=\"0.005\">0.0050",
+ "class=\"Has-number-with-prec2 smwtype_num\" data-sort-value=\"0.005\">0.01",
+ "class=\"Has-number smwtype_num\" data-sort-value=\"0.008\">0.008",
+ "class=\"Has-number-with-prec2 smwtype_num\" data-sort-value=\"42\">42.00",
+ "class=\"Has-number smwtype_num\" data-sort-value=\"42\">42",
+ "class=\"Has-number-with-prec2 smwtype_num\" data-sort-value=\"10000\">10,000.00",
+ "class=\"Has-number smwtype_num\" data-sort-value=\"10000\">10,000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 Prec2 vs Prec4 vs Prc0 quantity output",
+ "subject": "Example/P0410/4",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-area-with-prec4 smwtype_qty\" data-sort-value=\"0.02\"",
+ "0.0200&#160;km²",
+ "0.0077&#160;sqmi",
+ "20.0000&#160;m²",
+ "class=\"Has-area-with-prec2 smwtype_qty\" data-sort-value=\"10\"",
+ "10.00&#160;km²",
+ "3.86&#160;sqmi",
+ "10,000.00&#160;m²",
+ "class=\"Has-area-with-prec0 smwtype_qty\" data-sort-value=\"3.33\"",
+ "3&#160;km²",
+ "1&#160;sqmi",
+ "3,330&#160;m²"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 on currency output",
+ "subject": "Example/P0410/5",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-currency-with-prec4 smwtype_qty\" data-sort-value=\"0.87556397264388\"",
+ "€&#160;0.8756",
+ "Â¥&#160;100.0000",
+ "class=\"Has-currency-with-prec2 smwtype_qty\" data-sort-value=\"5\"",
+ "€&#160;5.00",
+ "Â¥&#160;571.06",
+ "class=\"Has-currency-with-prec4 smwtype_qty\" data-sort-value=\"0.0043778198632194\"",
+ "€&#160;0.0044",
+ "Â¥&#160;0.5000",
+ "class=\"Has-currency-with-prec2 smwtype_qty\" data-sort-value=\"5000\"",
+ "€&#160;5,000.00",
+ "Â¥&#160;571,060.50"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 on number output without property defined precision, uses -p4 printout marker",
+ "subject": "Example/P0410/6a",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-number smwtype_num\" data-sort-value=\"10000\"",
+ "10,000.00",
+ "0.01",
+ "42.01",
+ "1,001.00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 on number output without property defined precision, uses -p4 printout marker",
+ "subject": "Example/P0410/6b",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-number smwtype_num\" data-sort-value=\"10000\"",
+ "10,000.0000",
+ "0.0050",
+ "42.0050",
+ "1,001.0000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 on number output without property defined precision, uses -p3-n printout marker",
+ "subject": "Example/P0410/6c",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-number smwtype_num\" data-sort-value=\"10000\"",
+ "10000.000",
+ "0.005",
+ "42.005",
+ "1001.000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#10 on quantity output without property defined precision, uses -p2 printout marker",
+ "subject": "Example/P0410/7a",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-area smwtype_qty\" data-sort-value=\"10\"",
+ "10.00&#160;km²",
+ "3.86&#160;sqmi",
+ "10,000.00&#160;m²",
+ "0.02&#160;km²",
+ "0.01&#160;sqmi",
+ "20.00&#160;m²",
+ "3.33&#160;km²",
+ "1.29&#160;sqmi",
+ "3,330.00&#160;m²"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#11 on quantity output without property defined precision, uses m²-p3 printout marker",
+ "subject": "Example/P0410/7b",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-area smwtype_qty\" data-sort-value=\"10\"",
+ "10,000.000&#160;m²",
+ "10.000&#160;km²",
+ "3.861&#160;sqmi",
+ "20.000&#160;m²",
+ "0.020&#160;km²",
+ "0.008&#160;sqmi",
+ "3,330.000&#160;m²",
+ "3.330&#160;km²",
+ "1.286&#160;sqmi"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#12 on quantity output without property defined precision, uses -n-p2 printout marker",
+ "subject": "Example/P0410/7c",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-area smwtype_qty\" data-sort-value=\"10\"",
+ "10.00",
+ "0.02",
+ "3.33"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#13 on temperature output without property defined precision, uses -p2 printout marker",
+ "subject": "Example/P0410/8a",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-temperature smwtype_tem\" data-sort-value=\"273.15\"",
+ "class=\"smwtext\">273.15&#160;K",
+ "0.00&#160;°C",
+ "32.00&#160;°F",
+ "491.67&#160;°R",
+ "class=\"smwtext\">373.15&#160;K",
+ "100.00&#160;°C",
+ "212.00&#160;°F",
+ "671.67&#160;°R"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#14 on temperature output without property defined precision, uses °C-p3 printout marker",
+ "subject": "Example/P0410/8b",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-temperature smwtype_tem\" data-sort-value=\"273.15\"",
+ "class=\"smwtext\">0.000&#160;°C",
+ "273.150&#160;K",
+ "32.000&#160;°F",
+ "491.670&#160;°R",
+ "class=\"smwtext\">100.000&#160;°C",
+ "373.150&#160;K",
+ "212.000&#160;°F",
+ "671.670&#160;°R"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#15 on temperature output without property defined precision, uses -n-p2 printout marker",
+ "subject": "Example/P0410/8c",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-temperature smwtype_tem\" data-sort-value=\"273.15\"",
+ "273.15",
+ "373.15"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0411.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0411.json
new file mode 100644
index 00000000..26f07d33
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0411.json
@@ -0,0 +1,151 @@
+{
+ "description": "Test in-text annotation (and #subobject) using a monolingual property (#1344, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text with language",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "page": "Example/P0411/1",
+ "contents": "[[Has text with language::example one@en]]"
+ },
+ {
+ "page": "Example/P0411/1/1",
+ "contents": "{{#ask: [[Has text with language::example one@en]] |?Has text with language }}"
+ },
+ {
+ "page": "Example/P0411/1/2",
+ "contents": "{{#ask: [[-Has text with language::Example/P0411/1]] |?Language code |?Text }}"
+ },
+ {
+ "page": "Example/P0411/2",
+ "contents": "{{#subobject: |Has text with language=例ã®ä¸€@ja }} {{#subobject: |Has text with language=pour l'exemple@fr }}"
+ },
+ {
+ "page": "Example/P0411/2/1",
+ "contents": "{{#ask: [[Has text with language::?@ja]] |?Has text with language }}"
+ },
+ {
+ "page": "Example/P0411/2/2",
+ "contents": "{{#ask: [[Language code::ja]] |?Text }}"
+ },
+ {
+ "page": "Example/P0411/2/3",
+ "contents": "{{#ask: [[Language code::ja]] |?-Has text with language }}"
+ },
+ {
+ "page": "Example/P0411/3",
+ "contents": "{{#subobject: |Has text with language=国@zh-hans }} {{#subobject: |Has text with language=國@zh-hant }}"
+ },
+ {
+ "page": "Example/P0411/3/1",
+ "contents": "{{#ask: [[Has text with language::?@~zh*]] |?Has text with language=Text |+index=1 |?Has text with language=Code |+index=2 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0411/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_text_with_language",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": []
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "example one (en)"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 match subject",
+ "subject": "Example/P0411/1/1",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0411/1",
+ "class=\"Has-text-with-language smwtype_mlt_rec\">example one (en)"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 inverse match",
+ "subject": "Example/P0411/1/2",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0411/1#_ML3c1364d804527cd1594b4817b01c29f0",
+ "class=\"Language-code smwtype&#95;_lcode\">en",
+ "class=\"Text smwtype_txt\">example one"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 match specific language",
+ "subject": "Example/P0411/2/1",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0411/2#_b88331e53ca614aea6f7c8b5f0d6f876",
+ "class=\"Has-text-with-language smwtype_mlt_rec\">例ã®ä¸€ (ja)"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 match specific language",
+ "subject": "Example/P0411/2/2",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0411/2#_ML13e9d4c2ba826927d7210acab7def9ec",
+ "class=\"Text smwtype_txt\">例ã®ä¸€"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 match specific language with inverse printout",
+ "subject": "Example/P0411/2/3",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0411/2#_ML13e9d4c2ba826927d7210acab7def9ec",
+ "title=\"Property:Has text with language\">-Has text with language",
+ "class=\"-Has-text-with-language smwtype_mlt_rec\">Example/P0411/2"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 using index display for columns",
+ "subject": "Example/P0411/3/1",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0411/3#_a52273132da28d0c1fad5819e44958ab",
+ "class=\"Text smwtype_txt\">国",
+ "class=\"Code smwtype&#95;_lcode\">zh-Hans",
+ "Example/P0411/3#_4eac5791ab0478bb01dc9d181bc91ec8",
+ "class=\"Text smwtype_txt\">國",
+ "class=\"Code smwtype&#95;_lcode\">zh-Hant"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0412.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0412.json
new file mode 100644
index 00000000..8c6f716e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0412.json
@@ -0,0 +1,76 @@
+{
+ "description": "Test in-text annotation for `_boo` datatype (`wgContLang=ja`, `wgLang=ja`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has boolean",
+ "contents": "[[Has type::Boolean]]"
+ },
+ {
+ "page": "Example/P0412/1",
+ "contents": "[[Has boolean::真]]"
+ },
+ {
+ "page": "Example/P0412/2",
+ "contents": "{{#set:Has boolean=å½}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 true",
+ "subject": "Example/P0412/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_boolean",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ true
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 false",
+ "subject": "Example/P0412/2",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_boolean",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ false
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "ja",
+ "wgLang": "ja",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0413.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0413.json
new file mode 100644
index 00000000..5a4d28e2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0413.json
@@ -0,0 +1,882 @@
+{
+ "description": "Test in-text annotation for different `_dat` input/output (en, skip virtuoso, `smwgDVFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0413/1",
+ "contents": "[[Has date::Feb 11 2000 10:00:01]]"
+ },
+ {
+ "page": "Example/P0413/1a",
+ "contents": "{{#ask: [[Example/P0413/1]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/2",
+ "contents": "[[Has date::Feb 11 2000]]"
+ },
+ {
+ "page": "Example/P0413/2a",
+ "contents": "{{#ask: [[Example/P0413/2]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/3",
+ "contents": "[[Has date::2000]]"
+ },
+ {
+ "page": "Example/P0413/3a",
+ "contents": "{{#ask: [[Example/P0413/3]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/4",
+ "contents": "[[Has date::Feb 11 2000 10:00:01 PM]]"
+ },
+ {
+ "page": "Example/P0413/4a",
+ "contents": "{{#ask: [[Example/P0413/4]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/5",
+ "contents": "[[Has date::Feb 11 2000 22:00:01]]"
+ },
+ {
+ "page": "Example/P0413/5a",
+ "contents": "{{#ask: [[Example/P0413/5]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/6",
+ "contents": "[[Has date::2000-02-11T22:00:01]]"
+ },
+ {
+ "page": "Example/P0413/6a",
+ "contents": "{{#ask: [[Example/P0413/6]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/7",
+ "contents": "[[Has date::2000-02-11T22:00:01+02:00]]"
+ },
+ {
+ "page": "Example/P0413/7a",
+ "contents": "{{#ask: [[Example/P0413/7]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/8",
+ "contents": "[[Has date::2000 February 2]]"
+ },
+ {
+ "page": "Example/P0413/8a",
+ "contents": "{{#ask: [[Example/P0413/8]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/9",
+ "contents": "[[Has date::2-3-2000]]"
+ },
+ {
+ "page": "Example/P0413/9a",
+ "contents": "{{#ask: [[Example/P0413/9]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/10",
+ "contents": "[[Has date::2/3/2000]]"
+ },
+ {
+ "page": "Example/P0413/10a",
+ "contents": "{{#ask: [[Example/P0413/10]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "page": "Example/P0413/11",
+ "contents": "[[Has date::Jan 1 300 BC]]"
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "page": "Example/P0413/11a",
+ "contents": "{{#ask: [[Example/P0413/11]] |?Has date |?Has date#GR |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date |?Has date#JD=JD }}"
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "page": "Example/P0413/12",
+ "contents": "[[Has date::14000000000 BC]] (WIN-OS only allows 2147483647)"
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "page": "Example/P0413/12a",
+ "contents": "{{#ask: [[Example/P0413/12]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/13",
+ "contents": "[[Has date::Feb 11 2000 Jl]]"
+ },
+ {
+ "page": "Example/P0413/13a",
+ "contents": "{{#ask: [[Example/P0413/13]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date |?Has date#JL=JL Date |?Has date#GR=GR Date }}"
+ },
+ {
+ "page": "Example/P0413/14",
+ "contents": "[[Has date::Feb 11 1492 Gr]]"
+ },
+ {
+ "page": "Example/P0413/14a",
+ "contents": "{{#ask: [[Example/P0413/14]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date |?Has date#JL=JL Date |?Has date#GR=GR Date }}"
+ },
+ {
+ "page": "Example/P0413/15",
+ "contents": "[[Has date::Feb 11 2000 10:00 GMT]]"
+ },
+ {
+ "page": "Example/P0413/15a",
+ "contents": "{{#ask: [[Example/P0413/15]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date |?Has date#JL=JL Date |?Has date#GR=GR Date }}"
+ },
+ {
+ "page": "Example/P0413/16",
+ "contents": "[[Has date::2000-02-22]]"
+ },
+ {
+ "page": "Example/P0413/16a",
+ "contents": "{{#ask: [[Example/P0413/16]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "page": "Example/P0413/17",
+ "contents": "[[Has date::11000 BC]]"
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "page": "Example/P0413/17a",
+ "contents": "{{#ask: [[Example/P0413/17]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date }}"
+ },
+ {
+ "page": "Example/P0413/18",
+ "contents": "[[Has date::2488346.0804977 JD]]"
+ },
+ {
+ "page": "Example/P0413/18a",
+ "contents": "{{#ask: [[Example/P0413/18]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date |?Has date#JD=JD }}"
+ },
+ {
+ "page": "Example/P0413/19",
+ "contents": "[[Has date::2488346.0804977 MJD]]"
+ },
+ {
+ "page": "Example/P0413/19a",
+ "contents": "{{#ask: [[Example/P0413/19]] |?Has date |?Has date#- |?Has date#ISO=ISO Date |?Has date#MEDIAWIKI=MW Date |?Has date#JD=JD }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 Complete date with time",
+ "subject": "Example/P0413/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-11T10:00:01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 2000 10:00:01"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0413/1a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451585.9166782\">11 February 2000 10:00:01</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451585.9166782\">2000-02-11T10:00:01</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451585.9166782\">2000-02-11T10:00:01</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451585.9166782\">10:00, 11 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 Just a date",
+ "subject": "Example/P0413/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-11"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 2000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0413/2a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451585.5\">11 February 2000</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451585.5\">2000-02-11</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451585.5\">2000-02-11</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451585.5\">11 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 Yearby itself",
+ "subject": "Example/P0413/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-01-01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5",
+ "subject": "Example/P0413/3a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451544.5\">2000</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451544.5\">2000-01-01</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451544.5\">2000-01-01</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451544.5\">2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 Complete date with time, PM",
+ "subject": "Example/P0413/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-11T22:00:01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 2000 10:00:01 PM"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7",
+ "subject": "Example/P0413/4a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.4166782\">11 February 2000 22:00:01</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.4166782\">2000-02-11T22:00:01</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451586.4166782\">2000-02-11T22:00:01</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451586.4166782\">22:00, 11 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 Complete date with 24h time",
+ "subject": "Example/P0413/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-11T22:00:01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 2000 22:00:01"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9",
+ "subject": "Example/P0413/5a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.4166782\">11 February 2000 22:00:01</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.4166782\">2000-02-11T22:00:01</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451586.4166782\">2000-02-11T22:00:01</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451586.4166782\">22:00, 11 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#10 ISO-style date",
+ "subject": "Example/P0413/6",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-11T22:00:01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2000-02-11T22:00:01"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#11",
+ "subject": "Example/P0413/6a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.4166782\">11 February 2000 22:00:01</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.4166782\">2000-02-11T22:00:01</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451586.4166782\">2000-02-11T22:00:01</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451586.4166782\">22:00, 11 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#12 ISO-style date with offset",
+ "subject": "Example/P0413/7",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-11T20:00:01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2000-02-11T22:00:01+02:00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#13",
+ "subject": "Example/P0413/7a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.3333449\">11 February 2000 20:00:01</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451586.3333449\">2000-02-11T20:00:01</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451586.3333449\">2000-02-11T20:00:01</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451586.3333449\">20:00, 11 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#14 varying order of inputs",
+ "subject": "Example/P0413/8",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-02"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2000 February 2"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#15",
+ "subject": "Example/P0413/8a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451576.5\">2 February 2000</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451576.5\">2000-02-02</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451576.5\">2000-02-02</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451576.5\">2 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#16 preferred interpretation, month or day, sometimes depends on language settings",
+ "subject": "Example/P0413/9",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-03"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2-3-2000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#17",
+ "subject": "Example/P0413/9a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451577.5\">3 February 2000</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451577.5\">2000-02-03</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451577.5\">2000-02-03</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451577.5\">3 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#18 various kinds of separators (/) are recognized in all languages",
+ "subject": "Example/P0413/10",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-03"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2/3/2000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#19",
+ "subject": "Example/P0413/10a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451577.5\">3 February 2000</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451577.5\">2000-02-03</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451577.5\">2000-02-03</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451577.5\">3 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#20 Dates BC/Before common era",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "subject": "Example/P0413/11",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "--301-12-28"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Jan 1 300 BC"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#21",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "subject": "Example/P0413/11a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"1611848.5\">1 January 300 BC <sup>JL</sup></td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"1611848.5\">28 December 301 BC</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"1611848.5\">--301-12-28</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"1611848.5\">--301-12-28</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"1611848.5\">28 December 0000</td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"1611848.5\">1611848.5</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#24 Julian Calendar annotated date",
+ "subject": "Example/P0413/13",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-24"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 2000 Jl"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#25",
+ "subject": "Example/P0413/13a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451598.5\">11 February 2000 <sup>JL</sup></td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451598.5\">2000-02-24</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451598.5\">2000-02-24</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451598.5\">24 February 2000</td>",
+ "<td class=\"JL-Date smwtype_dat\" data-sort-value=\"2451598.5\">11 February 2000 <sup>JL</sup></td>",
+ "<td class=\"GR-Date smwtype_dat\" data-sort-value=\"2451598.5\">24 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#26 Gregorian Calendar annotated date",
+ "subject": "Example/P0413/14",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "1492-02-11"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 1492 Gr"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#27",
+ "subject": "Example/P0413/14a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2266042.5\">2 February 1492 <sup>JL</sup></td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2266042.5\">1492-02-11</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2266042.5\">1492-02-11</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2266042.5\">11 February 1492</td>",
+ "<td class=\"JL-Date smwtype_dat\" data-sort-value=\"2266042.5\">2 February 1492 <sup>JL</sup></td>",
+ "<td class=\"GR-Date smwtype_dat\" data-sort-value=\"2266042.5\">11 February 1492</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#28 Date with time zone shortcut",
+ "subject": "Example/P0413/15",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-11T10:00:00"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 2000 10:00 GMT"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#29",
+ "subject": "Example/P0413/15a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451585.9166667\">11 February 2000 10:00:00</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451585.9166667\">2000-02-11T10:00:00</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451585.9166667\">2000-02-11T10:00:00</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451585.9166667\">10:00, 11 February 2000</td>",
+ "<td class=\"JL-Date smwtype_dat\" data-sort-value=\"2451585.9166667\">29 January 2000 10:00:00 <sup>JL</sup></td>",
+ "<td class=\"GR-Date smwtype_dat\" data-sort-value=\"2451585.9166667\">11 February 2000 10:00:00</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#30 MySQL date format",
+ "subject": "Example/P0413/16",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2000-02-22"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2000-02-22"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#31",
+ "subject": "Example/P0413/16a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451596.5\">22 February 2000</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2451596.5\">2000-02-22</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2451596.5\">2000-02-22</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2451596.5\">22 February 2000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#32 Pre-history",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "subject": "Example/P0413/17",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "--11000-01-01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "11000 BC"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#33",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support BC/BCE dates"
+ },
+ "subject": "Example/P0413/17a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"-11001\">11000 BC</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"-11001\">--11000-01-01</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"-11001\">--11000-01-01</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"-11001\">0000</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#34 Direct JD input",
+ "subject": "Example/P0413/18",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2100-10-04T13:55:55"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2488346.0804977 JD"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#35",
+ "subject": "Example/P0413/18a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2488346.0804977\">4 October 2100 13:55:55</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2488346.0804977\">2100-10-04T13:55:55</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"2488346.0804977\">2100-10-04T13:55:55</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"2488346.0804977\">13:55, 4 October 2100</td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"2488346.0804977\">2488346.0804977</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#36 Direct MJD input",
+ "subject": "Example/P0413/19",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "8671-09-27T01:55:55"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2488346.0804977 MJD"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#37",
+ "subject": "Example/P0413/19a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"4888346.5804977\">27 September 8671 01:55:55</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"4888346.5804977\">8671-09-27T01:55:55</td>",
+ "<td class=\"ISO-Date smwtype_dat\" data-sort-value=\"4888346.5804977\">8671-09-27T01:55:55</td>",
+ "<td class=\"MW-Date smwtype_dat\" data-sort-value=\"4888346.5804977\">01:55, 27 September 8671</td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"4888346.5804977\">4888346.5804977</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDVFeatures": [
+ "SMW_DV_TIMEV_CM"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0414.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0414.json
new file mode 100644
index 00000000..817e13d9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0414.json
@@ -0,0 +1,395 @@
+{
+ "description": "Test in-text annotation/free format for `_dat` datatype (#1389, #1401, en, `smwgDVFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0414/1",
+ "contents": "[[Has date::Feb 11 1389 10:00:01]]"
+ },
+ {
+ "page": "Example/P0414/1a",
+ "contents": "{{#ask: [[Example/P0414/1]] |?Has date#-F[H:i:s.u] |?Has date#-F[Y/m/d H:i] |?Has date#GR-F[Y/m/d H:i] |?Has date#JD=JD }}"
+ },
+ {
+ "page": "Example/P0414/2",
+ "contents": "[[Has date::100000 BC]]"
+ },
+ {
+ "page": "Example/P0414/2a",
+ "contents": "{{#ask: [[Example/P0414/2]] |?Has date#-F[H:i:s.u] |?Has date#-F[Y/m/d H:i] |?Has date#GR-F[Y/m/d H:i] |?Has date#JD=JD }}"
+ },
+ {
+ "page": "Example/P0414/3",
+ "contents": "[[Has date::1902]]"
+ },
+ {
+ "page": "Example/P0414/3a",
+ "contents": "{{#ask: [[Example/P0414/3]] |?Has date#-F[Y] |?Has date#-F[Y/m/d] |?Has date#JD=JD }}"
+ },
+ {
+ "page": "Example/P0414/4",
+ "contents": "[[Has date::12001102120325]]"
+ },
+ {
+ "page": "Example/P0414/4a",
+ "contents": "{{#ask: [[Example/P0414/4]] |?Has date#-F[Y] |?Has date#-F[Y/m/d] |?Has date#JD=JD }}"
+ },
+ {
+ "page": "Example/P0414/5",
+ "contents": "[[Has date::-100000]]"
+ },
+ {
+ "page": "Example/P0414/5a",
+ "contents": "{{#ask: [[Example/P0414/5]] |?Has date#-F[H:i:s.u] |?Has date#-F[Y/m/d H:i] |?Has date#GR-F[Y/m/d H:i] |?Has date#JD=JD }}"
+ },
+ {
+ "page": "Example/P0414/6",
+ "contents": "[[Has date::1902 AD]]"
+ },
+ {
+ "page": "Example/P0414/6a",
+ "contents": "{{#ask: [[Example/P0414/6]] |?Has date |?Has date#-F[Y] |?Has date#-F[Y/m/d] }}"
+ },
+ {
+ "page": "Example/P0414/7",
+ "contents": "[[Has date::2012-07-08 11:14:15.888499949]]"
+ },
+ {
+ "page": "Example/P0414/7a",
+ "contents": "{{#ask: [[Example/P0414/7]] |?Has date |?Has date#-F[H:i:s.u] }}"
+ },
+ {
+ "page": "Example/P0414/8",
+ "contents": "[[Has date::2010年1月6日 16:57]]"
+ },
+ {
+ "page": "Example/P0414/8a",
+ "contents": "{{#ask: [[Example/P0414/8]] |?Has date |?Has date#-F[Y年m月d日 H:i] }}"
+ },
+ {
+ "page": "Example/P0414/9",
+ "contents": "[[Has date::2010年1月6日 16時57分]]"
+ },
+ {
+ "page": "Example/P0414/9a",
+ "contents": "{{#ask: [[Example/P0414/9]] |?Has date |?Has date#-F[Y年m月d日 H:i] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 JL calendar date with time",
+ "subject": "Example/P0414/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "1389-02-19T10:00:01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Feb 11 1389 10:00:01"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0414/1a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2228431.9166782\">10:00:01.000000</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2228431.9166782\">1389/02/11 10:00 <sup>JL</sup></td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2228431.9166782\">1389/02/19 10:00</td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"2228431.9166782\">2228431.9166782</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 Prehistory",
+ "subject": "Example/P0414/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "--100000-01-01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "100000 BC"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0414/2a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"-100001\">--100000-01-01</td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"-100001\">-34802824.5</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 year only",
+ "subject": "Example/P0414/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "1902-01-01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "1902"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5",
+ "subject": "Example/P0414/3a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2415750.5\">1902</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2415750.5\">1902/01/01</td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"2415750.5\">2415750.5</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 timestamp input (TS_MW as 'YmdHis)",
+ "subject": "Example/P0414/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "1200-11-02T12:03:25"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "12001102120325"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7",
+ "subject": "Example/P0414/4a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2159657.0023727\">1200 <sup>JL</sup></td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2159657.0023727\">1200/10/26 <sup>JL</sup></td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"2159657.0023727\">2159657.0023727</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 negative year without BC",
+ "subject": "Example/P0414/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "--100000-01-01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "-100000"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9",
+ "subject": "Example/P0414/5a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"-100001\">--100000-01-01</td>",
+ "<td class=\"JD smwtype_dat\" data-sort-value=\"-100001\">-34802824.5</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#10 positive year only with era marker",
+ "subject": "Example/P0414/6",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "AD 1902-01-01"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "1902 AD"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#11",
+ "subject": "Example/P0414/6a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2415750.5\">AD 1902</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2415750.5\">1902</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2415750.5\">1902/01/01</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#12 micro sec",
+ "subject": "Example/P0414/7",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2012-07-08T11:14:15"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2012-07-08 11:14:15.888499949"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#13 `.888499949` is being rounded to `.888500`",
+ "subject": "Example/P0414/7a",
+ "skip-on": {
+ "hhvm-*": "Avoid .888500 vs. .888499 msec issue due to hhvm#6899"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2456116.9682395\">8 July 2012 11:14:15</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2456116.9682395\">11:14:15.888500</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#14 Japanese date format",
+ "subject": "Example/P0414/8",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "2010-01-06T16:57:00"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2010年1月6日 16:57"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#15",
+ "subject": "Example/P0414/8a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2455203.20625\">6 January 2010 16:57:00</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2455203.20625\">2010年01月06日 16:57</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#16",
+ "subject": "Example/P0414/9a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2455203.20625\">6 January 2010 16:57:00</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2455203.20625\">2010年01月06日 16:57</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDVFeatures": [
+ "SMW_DV_TIMEV_CM"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0415.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0415.json
new file mode 100644
index 00000000..2f19eed8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0415.json
@@ -0,0 +1,65 @@
+{
+ "description": "Test in-text annotation on `_tem` with display unit preference (en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has temperature",
+ "contents": "[[Has type::Temperature]] [[Display unit::Celsius]]"
+ },
+ {
+ "page": "Example/P0415/1",
+ "contents": "[[Has temperature:: 32 °F]] [[Has temperature::100 °C]]"
+ },
+ {
+ "page": "Example/P0415/1a",
+ "contents": "{{#ask: [[Example/P0415/1]] |?Has temperature |?Has temperature#-=- |?Has temperature#-u=-u |?Has temperature#-n=-n |?Has temperature#°R=°R |format=table }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0415/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_temperature"
+ ],
+ "propertyValues": [
+ 273.15,
+ 373.15
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0415/1a",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwtext\">0&#160;°C</span><span class=\"smwttcontent\">273.15&#160;K <br />32&#160;°F <br />491.67&#160;°R <br /></span></span>",
+ "<span class=\"smwtext\">100&#160;°C</span><span class=\"smwttcontent\">373.15&#160;K <br />212&#160;°F <br />671.67&#160;°R <br /></span></span>",
+ "<td class=\"- smwtype_tem\" data-sort-value=\"273.15\">0 °C<br />100 °C</td>",
+ "<td class=\"-u smwtype_tem\" data-sort-value=\"273.15\">°C<br />°C</td>",
+ "<td class=\"-n smwtype_tem\" data-sort-value=\"273.15\">0 <br />100 </td>",
+ "<span class=\"smwtext\">491.67&#160;°R</span><span class=\"smwttcontent\">0&#160;°C <br />273.15&#160;K <br />32&#160;°F <br /></span></span>",
+ "<span class=\"smwtext\">671.67&#160;°R</span><span class=\"smwttcontent\">100&#160;°C <br />373.15&#160;K <br />212&#160;°F <br /></span></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0416.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0416.json
new file mode 100644
index 00000000..2f97e148
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0416.json
@@ -0,0 +1,281 @@
+{
+ "description": "Test in-text annotation with DISPLAYTITLE (#1410, #1611, `wgRestrictDisplayTitle`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Dwc:vernacularName",
+ "contents": "[[Has type::Text]] {{DISPLAYTITLE:dwc:vernacularName}}"
+ },
+ {
+ "page": "Example/P0416/1",
+ "contents": "{{DISPLAYTITLE:Foo}} {{#subobject:Bar|text=abc|Display title of=123}}"
+ },
+ {
+ "page": "Example/P0416/Q1.1",
+ "contents": "{{#ask: [[~Foo]] OR [[~123*]] |?Display title of |format=table }}"
+ },
+ {
+ "page": "Example/P0416/2",
+ "contents": "{{DISPLAYTITLE:Foobar}} {{#subobject:Bar|text=abc}}"
+ },
+ {
+ "page": "Example/P0416/Q2.1",
+ "contents": "{{#ask: [[~Example/P0416/2*]] OR [[~Foobar*]] |?Display title of |format=table }}"
+ },
+ {
+ "page": "Example/P0416/3",
+ "contents": "[[dwc:vernacularName::Gewoon struisgras]] {{DISPLAYTITLE:Agrostis capillaris}}"
+ },
+ {
+ "page": "Example/P0416/Q3.1",
+ "contents": "{{#ask: [[~Agrostis*]] |?dwc:vernacularName |format=table }}"
+ },
+ {
+ "page": "Example/P0416/4",
+ "contents": "{{DISPLAYTITLE:Foo}} {{DEFAULTSORTKEY:BAR}}"
+ },
+ {
+ "page": "Example/P0416/5",
+ "contents": "{{DISPLAYTITLE:Foo}} {{#subobject:|@sortkey=SORT}} {{#show: Example/P0416/5 |?Has subobject}}"
+ },
+ {
+ "page": "Example/P0416/6/1",
+ "contents": "{{DISPLAYTITLE:P0416}} {{#subobject:@category=P0416}} [[Category:P0416]]"
+ },
+ {
+ "page": "Example/P0416/6/2",
+ "contents": "{{DISPLAYTITLE:P0416}} {{DEFAULTSORT:BAR}} {{#subobject:@category=P0416}} [[Category:P0416]]"
+ },
+ {
+ "page": "Example/P0416/6/3",
+ "contents": "{{DISPLAYTITLE:P0416}} {{#subobject:@category=P0416|@sortkey=DEF}} [[Category:P0416]]"
+ },
+ {
+ "page": "Example/P0416/7",
+ "contents": "{{DISPLAYTITLE:ABC & DEF}}, see #1611"
+ },
+ {
+ "page": "Example/P0416/8'a",
+ "contents": "{{DISPLAYTITLE:<span style=\"position: absolute; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px);\">{{FULLPAGENAME}}</span>}} "
+ },
+ {
+ "page": "Example/P0416/Q6.1",
+ "contents": "{{#ask: [[Category:P0416]] [[~P0416*]] |link=none |format=table |sort=# |order=asc}}"
+ },
+ {
+ "page": "Example/P0416/Q6.2.1",
+ "contents": "{{#ask: [[Category:P0416]] [[~BAR]] |link=none |format=table |sort=# |order=asc}}"
+ },
+ {
+ "page": "Example/P0416/Q6.2.2",
+ "contents": "{{#ask: [[Category:P0416]] [[~BAR*]] |link=none |format=table |sort=# |order=asc}}"
+ },
+ {
+ "page": "Example/P0416/Q6.3",
+ "contents": "{{#ask: [[Category:P0416]] [[~DEF]] |link=none |format=table |sort=# |order=asc}}"
+ },
+ {
+ "page": "Example/P0416/Q7.1",
+ "contents": "{{#ask: [[Display title of::ABC & DEF]] |link=none |format=table |sort=# |order=asc}}"
+ },
+ {
+ "page": "Example/P0416/Q8.1",
+ "contents": "{{#ask: [[Display title of::Example/P0416/8'a]] |link=none |format=table |sort=# |order=asc}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0416/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_DTITLE",
+ "_SOBJ"
+ ],
+ "propertyValues": [
+ "Foo"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0416/1#Bar",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_DTITLE",
+ "_TEXT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "abc",
+ "123"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0416/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0416/1\">Foo</a></td><td class=\"Display-title-of smwtype_txt\">Foo</td>",
+ "title=\"Example/P0416/1\">123#Bar</a></span></td><td class=\"Display-title-of smwtype_txt\" data-sort-value=\"123\">123</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0416/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0416/2\">Foobar</a></td><td class=\"Display-title-of smwtype_txt\">Foobar</td>",
+ "title=\"Example/P0416/2\">Foobar#Bar</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4",
+ "subject": "Example/P0416/Q3.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0416/3\">Agrostis capillaris</a></td><td class=\"dwc:vernacularName smwtype_txt\">Gewoon struisgras</td>",
+ "title=\"Property:Dwc:vernacularName\">dwc:vernacularName</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5",
+ "subject": "Example/P0416/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_DTITLE",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "Foo",
+ "BAR"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6",
+ "subject": "Example/P0416/5#_47ab3a24a41d0687c9398e1886c38fe3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 1,
+ "propertyKeys": [
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "SORT"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7",
+ "subject": "Example/P0416/5",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0416/5#_47ab3a24a41d0687c9398e1886c38fe3\" title=\"Example/P0416/5\">Foo</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 (sortkey is copied from root, [1 and 3 contain both P0416 as sort while 1(sobj) contains P0416# ... ])",
+ "subject": "Example/P0416/Q6.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0416/6/1</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0416/6/3</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0416/6/1#_4c8278b5823715af48e85d55f6118d4e</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 (sortkey is copied from root, strict ~BAR)",
+ "subject": "Example/P0416/Q6.2.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0416/6/2</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#10 (sortkey is copied from root, ~BAR*)",
+ "subject": "Example/P0416/Q6.2.2",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0416/6/2</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0416/6/2#_4c8278b5823715af48e85d55f6118d4e</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#11 (sobj sortkey)",
+ "subject": "Example/P0416/Q6.3",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0416/6/3#_b6f2e00f3a822fef179c8c2ea8e0c987</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#12 Display title/query includes &",
+ "subject": "Example/P0416/Q7.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0416/7</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#13 Display title/query includes '",
+ "subject": "Example/P0416/Q8.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0416/8'a</td></tr>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgRestrictDisplayTitle": false
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0417.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0417.json
new file mode 100644
index 00000000..63bc7f5d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0417.json
@@ -0,0 +1,88 @@
+{
+ "description": "Test in-text annotation for `Allows pattern` to match regular expressions (en)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw allows pattern",
+ "contents": "...\n Whitelist|^(FooOnWhitelist|Bar|Foo bar)$\n IPv4|^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$\n"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has whitelist",
+ "contents": "[[Has type::Text]] [[Allows pattern::Whitelist]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "IPv4",
+ "contents": "[[Has type::Text]] [[Allows pattern::IPv4]]"
+ },
+ {
+ "page": "Example/P0417/1",
+ "contents": "[[Has whitelist::FooOnWhitelist]] [[Has whitelist::Foobar]]"
+ },
+ {
+ "page": "Example/P0417/2",
+ "contents": "[[IPv4::192.168.0.100]] [[IPv4::192.168.0.256]]"
+ },
+ {
+ "page": "Example/P0417/1a",
+ "contents": "{{#ask: [[Example/P0417/1]] |?Has whitelist |format=table }}"
+ },
+ {
+ "page": "Example/P0417/2a",
+ "contents": "{{#ask: [[Example/P0417/2]] |?IPv4 |format=table }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0, value Foobar is not allowed",
+ "subject": "Example/P0417/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_whitelist",
+ "_ERRC"
+ ],
+ "propertyValues": [
+ "FooOnWhitelist"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0417/1a",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0417/1\">Example/P0417/1</a></td><td class=\"Has-whitelist smwtype_txt\">FooOnWhitelist</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0417/2a",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0417/2\">Example/P0417/2</a></td><td class=\"IPv4 smwtype_txt\">192.168.0.100</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "skip-on": [],
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0418.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0418.json
new file mode 100644
index 00000000..69e8f958
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0418.json
@@ -0,0 +1,85 @@
+{
+ "description": "Test in-text annotation using `_SERV` as provide service links (en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "PropertyWithServiceLink",
+ "contents": "[[Has type::Text]] [[Provides service::some links]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "PropertyWithAnotherServiceLink",
+ "contents": "[[Has type::Text]] [[Provides service::some other links]]"
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw_service_some_other_links",
+ "contents": " label text1|http://someurl.com"
+ },
+ {
+ "page": "Example/P0418/1",
+ "contents": " [[PropertyWithServiceLink::123]]"
+ },
+ {
+ "page": "Example/P0418/2",
+ "contents": " [[PropertyWithAnotherServiceLink::ABC]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "PropertyWithServiceLink",
+ "namespace": "SMW_NS_PROPERTY",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_TYPE",
+ "_MDAT",
+ "_SKEY",
+ "_SERV"
+ ],
+ "propertyValues": [
+ "some links"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "PropertyWithServiceLink",
+ "namespace": "SMW_NS_PROPERTY",
+ "assert-output": {
+ "to-contain": [
+ "some links"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "PropertyWithAnotherServiceLink",
+ "namespace": "SMW_NS_PROPERTY",
+ "assert-output": {
+ "to-contain": [
+ "some other links"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0419.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0419.json
new file mode 100644
index 00000000..bdb41456
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0419.json
@@ -0,0 +1,285 @@
+{
+ "description": "Test in-text annotation for `_PVUC` to validate uniqueness (`smwgDVFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has Url",
+ "contents": "[[Has type::URL]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has monolingual text",
+ "contents": "[[Has type::Monolingual text]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has numeric reference",
+ "contents": "[[Has type::Reference]] [[Has fields::Number;Date]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has uniqueness record",
+ "contents": "[[Has type::Record]] [[Has fields::Number;Date]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "page": "Example/P0419/1",
+ "contents": "[[Has Url::http://example.org/P0419]]"
+ },
+ {
+ "page": "Example/P0419/2",
+ "contents": "[[Has Url::http://example.org/P0419]] [[Has Url::http://example.org/P0419-1]]"
+ },
+ {
+ "page": "Example/P0419/3",
+ "contents": "[[Has text::P0419]]"
+ },
+ {
+ "page": "Example/P0419/4",
+ "contents": "[[Has text::P0419]]"
+ },
+ {
+ "page": "Example/P0419/5",
+ "contents": "[[Has date::1 Jan 1970 12:50:12]]"
+ },
+ {
+ "page": "Example/P0419/6",
+ "contents": "{{#subobject:|Has date=1 Jan 1970 12:50:12}}"
+ },
+ {
+ "page": "Example/P0419/7",
+ "contents": "[[Has monolingual text::Foo@en]]"
+ },
+ {
+ "page": "Example/P0419/8",
+ "contents": "{{#subobject:|Has monolingual text=Foo@en}}"
+ },
+ {
+ "page": "Example/P0419/9",
+ "contents": "[[Has numeric reference::42;1 Jan 1970]]"
+ },
+ {
+ "page": "Example/P0419/9/1",
+ "contents": "[[Has numeric reference::42;1 Jan 1970]]"
+ },
+ {
+ "page": "Example/P0419/9/2",
+ "contents": "[[Has numeric reference::42;1 Jan 1970 12:00]]"
+ },
+ {
+ "page": "Example/P0419/10",
+ "contents": "[[Has uniqueness record::42;1 Jan 1970]]"
+ },
+ {
+ "page": "Example/P0419/10/1",
+ "contents": "[[Has uniqueness record::42;1 Jan 1970]]"
+ },
+ {
+ "page": "Example/P0419/10/2",
+ "contents": "[[Has uniqueness record::42;1 Jan 1970 12:00]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0419/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_Url"
+ ],
+ "propertyValues": [
+ "http://example.org/P0419"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0419/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC",
+ "Has_Url"
+ ],
+ "propertyValues": [
+ "http://example.org/P0419-1"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0419/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_text"
+ ],
+ "propertyValues": [
+ "P0419"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 Fails uniqueness for the text annotated in Example/P0419/3",
+ "subject": "Example/P0419/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 Fails uniqueness for date value annotated in Example/P0419/5",
+ "subject": "Example/P0419/6#_9fbec9d56750049a3420802d55db9a62",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "_SKEY",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 Fails uniqueness for monolingual text value annotated in Example/P0419/7",
+ "subject": "Example/P0419/8#_7d241515e1224e118e0cd09f9b055a79",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "_SKEY",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (Fails uniqueness due to same reference in Example/P0419/9)",
+ "subject": "Example/P0419/9/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 (same number but different date as in Example/P0419/9)",
+ "subject": "Example/P0419/9/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has numeric reference"
+ ],
+ "propertyValues": [
+ "Example/P0419/9/2#0##_REF31fea0d5c8403916c6f1da7c68f3998f"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 (Fails uniqueness due to same record in Example/P0419/10)",
+ "subject": "Example/P0419/10/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 (same number but different date as in Example/P0419/10)",
+ "subject": "Example/P0419/10/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has uniqueness record"
+ ],
+ "propertyValues": [
+ "Example/P0419/10/2#0##_fdf9ee62dae77aa0c5d7cf89d1faa64d"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "smwgDVFeatures": [
+ "SMW_DV_PVUC"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0420.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0420.json
new file mode 100644
index 00000000..356d2f20
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0420.json
@@ -0,0 +1,108 @@
+{
+ "description": "Test in-text annotation for `_dat` using JL/GR annotated values (en, `smwgDVFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0420/1",
+ "contents": "[[Has date::21 March 1685 JL]]"
+ },
+ {
+ "page": "Example/P0420/2",
+ "contents": "[[Has date::21 March 1685 Jl]]"
+ },
+ {
+ "page": "Example/P0420/3",
+ "contents": "[[Has date::21 March 1685 GR]]"
+ },
+ {
+ "page": "Example/P0420/1a",
+ "contents": "{{#ask: [[Example/P0420/1]] |?Has date |?Has date#GR |?Has date#JL }}"
+ },
+ {
+ "page": "Example/P0420/2a",
+ "contents": "{{#ask: [[Example/P0420/2]] |?Has date |?Has date#GR |?Has date#JL }}"
+ },
+ {
+ "page": "Example/P0420/3a",
+ "contents": "{{#ask: [[Example/P0420/3]] |?Has date |?Has date#GR |?Has date#JL }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 JL calendar date with time",
+ "subject": "Example/P0420/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "1685-03-31"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "21 March 1685 JL"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 JL",
+ "subject": "Example/P0420/1a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336583.5\">21 March 1685 <sup>JL</sup></td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336583.5\">31 March 1685</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336583.5\">21 March 1685 <sup>JL</sup></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 JL",
+ "subject": "Example/P0420/2a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336583.5\">21 March 1685 <sup>JL</sup></td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336583.5\">31 March 1685</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336583.5\">21 March 1685 <sup>JL</sup></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 GR",
+ "subject": "Example/P0420/3a",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336573.5\">21 March 1685</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336573.5\">21 March 1685</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2336573.5\">11 March 1685 <sup>JL</sup></td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDVFeatures": [
+ "SMW_DV_TIMEV_CM"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0421.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0421.json
new file mode 100644
index 00000000..eecd86b6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0421.json
@@ -0,0 +1,55 @@
+{
+ "description": "Test in-text annotation with combined constraint validation `_PVUC` and `_PVAL` (`smwgDVFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has uniqueness url",
+ "contents": "[[Has type::URL]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]] [[Allows value::open]]"
+ },
+ {
+ "page": "Example/P0421/1",
+ "contents": "[[Has uniqueness url::http://example.org/P0421]] [[Has text::open]]"
+ },
+ {
+ "page": "Example/P0421/2",
+ "contents": "[[Has uniqueness url::http://example.org/P0421]] [[Has text::closed]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 Fails on both constraints due to Example/P0421/1",
+ "subject": "Example/P0421/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ }
+ ],
+ "settings": {
+ "smwgDVFeatures": [
+ "SMW_DV_PVUC"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0422.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0422.json
new file mode 100644
index 00000000..8f795a56
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0422.json
@@ -0,0 +1,124 @@
+{
+ "description": "Test in-text annotation `_dat` on partial dates (#2076, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0422/1",
+ "contents": "[[Has date::Jan 1990]], [[Has date::02 1990]], [[Has date::1782]], [[Has date::1990å¹´6月]], [[Has date::1990å¹´4月28æ—¥ 7時01分]], [[Has date::199ï¼å¹´ï¼™æœˆ]]"
+ },
+ {
+ "page": "Example/P0422/Q/1",
+ "contents": "{{#show: Example/P0422/1 |?Has date }}"
+ },
+ {
+ "page": "Example/P0422/2",
+ "contents": "{{#subobject:|Has date=Jan 1923|@category=Partial dates}} {{#subobject:|Has date=Feb 1960|@category=Partial dates}} {{#subobject:|Has date=1645|@category=Partial dates}}"
+ },
+ {
+ "page": "Example/P0422/Q/2/1",
+ "contents": "{{#ask: [[Category:Partial dates]] |?Has date |sort=Has date|order=asc |link=none }}"
+ },
+ {
+ "page": "Example/P0422/Q/2/2",
+ "contents": "{{#ask: [[Category:Partial dates]] |?Has date |sort=Has date|order=desc |link=none }}"
+ },
+ {
+ "page": "Example/P0422/3",
+ "contents": "[[Has date::0]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0422/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_date"
+ ],
+ "propertyValues": [
+ "1990-01-01",
+ "1990-02-01",
+ "1782-01-01",
+ "1990-06-01",
+ "1990-04-28T07:01:00",
+ "1990-09-01"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0422/Q/1",
+ "assert-output": {
+ "to-contain": [
+ "January 1990",
+ "February 1990",
+ "1782",
+ "June 1990",
+ "28 April 1990 07:01:00",
+ "September 1990"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (sort asc)",
+ "subject": "Example/P0422/Q/2/1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0422/2#_eda78f1641edf981597b59b79f9a8c1f</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2321884.5\">1645</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0422/2#_23b1a59a99dd05132dabb6cf45cb40b3</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2423420.5\">January 1923</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0422/2#_f9a370d40ebd98e67c2b884fc09c7f9d</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2436965.5\">February 1960</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (sort desc)",
+ "subject": "Example/P0422/Q/2/2",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0422/2#_f9a370d40ebd98e67c2b884fc09c7f9d</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2436965.5\">February 1960</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0422/2#_23b1a59a99dd05132dabb6cf45cb40b3</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2423420.5\">January 1923</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0422/2#_eda78f1641edf981597b59b79f9a8c1f</td><td class=\"Has-date smwtype_dat\" data-sort-value=\"2321884.5\">1645</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (#2076, output an error instead of an exception)",
+ "subject": "Example/P0422/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0423.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0423.json
new file mode 100644
index 00000000..6a0b4a32
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0423.json
@@ -0,0 +1,173 @@
+{
+ "description": "Test in-text annotation / `#ask` (#MEDIAWIKI, #LOCL) output for `_dat` datatype (#1545, `wgContLang=en`, `wgLang=ja`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0423/1",
+ "contents": "[[Has date::12 Jan 1957 12:05]]"
+ },
+ {
+ "contentlanguage": "fr",
+ "page": "Example/P0423/2",
+ "contents": "[[Has date::12 April 1957 12:05]]"
+ },
+ {
+ "page": "Example/P0423/Q1.1",
+ "contents": "{{#ask: [[Has date::12 Jan 1957 12:05]] |?Has date |?Has date#MEDIAWIKI }}"
+ },
+ {
+ "page": "Example/P0423/Q1.2",
+ "contents": "{{#show: Example/P0423/1 |?Has date |?Has date#MEDIAWIKI }}"
+ },
+ {
+ "page": "Example/P0423/Q1.3",
+ "contents": "{{#ask: [[Has date::12 Jan 1957 12:05]] |?Has date#LOCL }}"
+ },
+ {
+ "page": "Example/P0423/Q1.4",
+ "contents": "{{#show: Example/P0423/1 |?Has date#LOCL }}"
+ },
+ {
+ "page": "Example/P0423/Q1.5",
+ "contents": "{{#show: Example/P0423/1 |?Has date#LOCL@fr }}"
+ },
+ {
+ "page": "Example/P0423/Q2.1",
+ "contents": "{{#show: Example/P0423/2 |?Has date }}"
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support `-4715-11-24T12:00:00Z\"^^xsd:dateTime` and goes '...Error: Malformed query...'"
+ },
+ "page": "Example/P0423/3",
+ "contents": "[[Has date::Jan 10000000000]]"
+ },
+ {
+ "page": "Example/P0423/Q3.1",
+ "contents": "{{#ask: [[Example/P0423/3]] |?Has date#LOCL }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0423/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_date",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "1957-01-12T12:05:00"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "12 Jan 1957 12:05"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (#ask MEDIAWIKI)",
+ "subject": "Example/P0423/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2435851.0034722\">12 January 1957 12:05:00</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2435851.0034722\">1957年1月12日 (土) 12:05</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (#show MEDIAWIKI)",
+ "subject": "Example/P0423/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_dat\" data-sort-value=\"2435851.0034722\">12 January 1957 12:05:00</td>",
+ "<td class=\"smwtype_dat\" data-sort-value=\"2435851.0034722\">1957年1月12日 (土) 12:05</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (#ask LOCL)",
+ "subject": "Example/P0423/Q1.3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2435851.0034722\">1957年1月12日 (土) 12:05:00</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (#show LOCL for user lang)",
+ "subject": "Example/P0423/Q1.4",
+ "assert-output": {
+ "to-contain": [
+ "1957年1月12日 (土) 12:05:00"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (#show LOCL@fr for annotated fr lang and not for user lang)",
+ "subject": "Example/P0423/Q1.5",
+ "assert-output": {
+ "to-contain": [
+ "12:05:00, 12 janvier 1957"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 page vs global content language",
+ "subject": "Example/P0423/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "12 April 1957 12:05:00"
+ ],
+ "not-contain": [
+ "12 avril 1957 12:05:00"
+ ]
+ }
+ },
+ {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1, see Example/P0423/3 comment!"
+ },
+ "type": "parser",
+ "about": "#7 avoid a possible `DateTime ... Failed to parse time ...` on large dates, only checking some minor output since WINOS reports 784354016999.5, yet Linux returns 3652426721059.5 (float precision issue)",
+ "subject": "Example/P0423/Q3.1",
+ "assert-output": {
+ "to-contain": [
+ "class=\"Has-date smwtype_dat\" "
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "ja",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0424.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0424.json
new file mode 100644
index 00000000..b9488881
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0424.json
@@ -0,0 +1,115 @@
+{
+ "description": "Test in-text annotation for `_boo` datatype using `LOCL` (`wgContLang=en`, `wgLang=fr`, skip-on 1.25.6)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has boolean",
+ "contents": "[[Has type::Boolean]]"
+ },
+ {
+ "page": "Example/P0424/1",
+ "contents": "[[Has boolean::true]] [[Category:P0424]]"
+ },
+ {
+ "page": "Example/P0424/2",
+ "contents": "{{#set:Has boolean=false}} [[Category:P0424]]"
+ },
+ {
+ "page": "Example/P0424/Q1.1",
+ "contents": "{{#ask: [[Category:P0424]] |?Has boolean |?Has boolean#LOCL}}"
+ },
+ {
+ "page": "Example/P0424/Q1.2",
+ "contents": "{{#ask: [[Category:P0424]] |?Has boolean |?Has boolean#LOCL@ja}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 true",
+ "subject": "Example/P0424/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_boolean",
+ "_SKEY",
+ "_MDAT",
+ "_INST"
+ ],
+ "propertyValues": [
+ true
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 false",
+ "subject": "Example/P0424/2",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_boolean",
+ "_SKEY",
+ "_MDAT",
+ "_INST"
+ ],
+ "propertyValues": [
+ false
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 LOCL used the user language",
+ "subject": "Example/P0424/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"1\">true</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"1\">vrai</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"0\">false</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"0\">faux</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 LOCL@js uses a specific language",
+ "subject": "Example/P0424/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"1\">true</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"1\">真</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"0\">false</td>",
+ "<td class=\"Has-boolean smwtype_boo\" data-sort-value=\"0\">å½</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "fr",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "mw-1.25.6": "Somehow the content lang is not set correctly on Travis (locally works fine)."
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0425.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0425.json
new file mode 100644
index 00000000..e2db98de
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0425.json
@@ -0,0 +1,71 @@
+{
+ "description": "Test in-text annotation on `_tem`/ `_num` with different page content language (#1591, `wgContLang=es`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has temperature",
+ "contents": "[[Has type::Temperature]]"
+ },
+ {
+ "contentlanguage": "fr",
+ "page": "Example/P0425/1",
+ "contents": "[[Has temperature::310.928 K]]"
+ },
+ {
+ "contentlanguage": "en",
+ "page": "Example/P0425/2",
+ "contents": "[[Has temperature::310.928 K]]"
+ },
+ {
+ "contentlanguage": "fr",
+ "page": "Example/P0425/3",
+ "contents": "[[Has temperature::310,928 K]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 page content language FR and . do not match, uses `en` as display language",
+ "subject": "Example/P0425/1",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwttcontent\">\".928K\" is not declared as a valid unit of measurement for this property.</span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 page content language EN and . do match",
+ "subject": "Example/P0425/2",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwtext\">310.928 K</span><span class=\"smwttcontent\">37.778&#160;°C <br />100&#160;°F <br />559.67&#160;°R <br /></span></span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 page content language FR and , do match",
+ "subject": "Example/P0425/3",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwtext\">310,928 K</span><span class=\"smwttcontent\">37.778&#160;°C <br />100&#160;°F <br />559.67&#160;°R <br /></span></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgLang": "en",
+ "wgContLang": "es",
+ "wgLanguageCode": "es",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0426.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0426.json
new file mode 100644
index 00000000..a80d6f22
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0426.json
@@ -0,0 +1,104 @@
+{
+ "description": "Test in-text annotation for `_num` on big/small numbers/scientific notation (`wgContLang=fr`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number with precision 4",
+ "contents": "[[Has type::Number]] [[Display precision of::4]]"
+ },
+ {
+ "contentlanguage": "fr",
+ "page": "Example/P0426/1",
+ "contents": "[[Has number::0,00000000000012]] [[Has number::1,000000000000123]] [[Has number::72,769482308]] [[Has number::5000,769482308]] [[Has number::-0,000000000004566]] [[Has number::0,2123456e+3]] [[Has number::1,334e-13]]"
+ },
+ {
+ "contentlanguage": "en",
+ "page": "Example/P0426/2",
+ "contents": "[[Has number::0.00000000000012]] [[Has number::1.000000000000123]] [[Has number::72.769482308]] [[Has number::5000.769482308]] [[Has number::-0.000000000004566]] [[Has number::0.2123456e+3]] [[Has number::1.334e-13]]"
+ },
+ {
+ "contentlanguage": "fr",
+ "page": "Example/P0426/Q1.1",
+ "contents": "{{#ask: [[Example/P0426/1]] |?Has number }}"
+ },
+ {
+ "contentlanguage": "fr",
+ "page": "Example/P0426/Q1.2",
+ "contents": "{{#ask: [[Example/P0426/1]] |?Has number#-p5 }}"
+ },
+ {
+ "contentlanguage": "fr",
+ "page": "Example/P0426/Q2.1",
+ "contents": "{{#ask: [[Example/P0426/2]] |?Has number }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 page content language FR, display in en",
+ "subject": "Example/P0426/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "1.2e-13",
+ "1",
+ "72.769",
+ "5,000.769",
+ "-4.566e-12",
+ "212.346",
+ "1.334e-13"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 page content language EN, display in en",
+ "subject": "Example/P0426/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "1.2e-13",
+ "1",
+ "72.769",
+ "5,000.769",
+ "-4.566e-12",
+ "212.346",
+ "1.334e-13"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 with precision display precision 5",
+ "subject": "Example/P0426/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "0.00000",
+ "1.00000",
+ "72.76948",
+ "5,000.76948",
+ "-0.00000",
+ "212.34560",
+ "0.00000"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgLang": "en",
+ "wgContLang": "fr",
+ "wgLanguageCode": "fr",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0427.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0427.json
new file mode 100644
index 00000000..898ee85c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0427.json
@@ -0,0 +1,146 @@
+{
+ "description": "Test in-text annotation with DISPLAYTITLE / `foaf` to check on upper vs. lower case (`wgRestrictDisplayTitle`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import foaf",
+ "contents": "http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name|Type:Text\n homepage|Type:URL\n mbox|Type:Email\n mbox_sha1sum|Type:Text\n depiction|Type:URL\n phone|Type:Text\n Person|Category\n Organization|Category\n knows|Type:Page\n member|Type:Page\n"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:homepage",
+ "contents": "[[Imported from::foaf:homepage]] {{DISPLAYTITLE:foaf:homepage}} [[Has property description::URL representing ... @en]] [[Category:Imported vocabulary]]"
+ },
+ {
+ "page": "Example/P0427/Q0.1",
+ "contents": "{{#show: Property:Foaf:homepage |?Has property description}}"
+ },
+ {
+ "page": "Example/P0427/Q0.2",
+ "contents": "{{#ask: [[Property:+]][[Category:Imported vocabulary]] |?Has property description=Description |link=none}}"
+ },
+ {
+ "page": "Example/P0427/1",
+ "contents": "{{#subobject: |Has text=abc |display title of=ab c123 |@category=P0427 }}{{#subobject: |Has text=ABC |display title of=AB C123 |@category=P0427 }}"
+ },
+ {
+ "page": "Example/P0427/Q1.1",
+ "contents": "{{#ask: [[Category:P0427]] [[~ab c*]] |?Has text |link=none}}"
+ },
+ {
+ "page": "Example/P0427/Q1.2",
+ "contents": "{{#ask: [[Category:P0427]] [[~AB C*]] |?Has text |link=none}}"
+ },
+ {
+ "page": "Example/P0427/Q1.3",
+ "contents": "{{#ask: [[Example/P0427/1#_7cae05fedd48fa820a0ea915518cc3fd]] |?Has text |link=none}}"
+ },
+ {
+ "page": "Example/P0427/Q1.4",
+ "contents": "{{#ask: [[Category:P0427]] [[!~ab c*]] |?Has text |link=none}}"
+ },
+ {
+ "page": "Example/P0427/Q1.5",
+ "contents": "{{#ask: [[Category:P0427]] [[!~AB C*]] |?Has text |link=none}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 match foaf:homepage to Property:Foaf:homepage",
+ "subject": "Example/P0427/Q0.1",
+ "assert-output": {
+ "to-contain": [
+ "URL representing ... (en)"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0427/Q0.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Property:Foaf:homepage</td>",
+ "<td class=\"Description smwtype_mlt_rec\">URL representing ... (en)</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 only match `abc*`",
+ "subject": "Example/P0427/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0427/1#_7cae05fedd48fa820a0ea915518cc3fd</td>",
+ "<td class=\"Has-text smwtype_txt\">abc</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 only match `ABC*`",
+ "subject": "Example/P0427/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0427/1#_6840005f556d165faf53ecf39be9ee97</td>",
+ "<td class=\"Has-text smwtype_txt\">ABC</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 same as #2",
+ "subject": "Example/P0427/Q1.3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0427/1#_7cae05fedd48fa820a0ea915518cc3fd</td>",
+ "<td class=\"Has-text smwtype_txt\">abc</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 to be reverse to #2",
+ "subject": "Example/P0427/Q1.4",
+ "skip-on": {
+ "elastic": "ES matches both `AB C` and `ab c` which is why the result set is 0"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0427/1#_6840005f556d165faf53ecf39be9ee97</td>",
+ "<td class=\"Has-text smwtype_txt\">ABC</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 to be reverse to #3",
+ "subject": "Example/P0427/Q1.5",
+ "skip-on": {
+ "elastic": "ES matches both `AB C` and `ab c` which is why the result set is 0"
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0427/1#_7cae05fedd48fa820a0ea915518cc3fd</td>",
+ "<td class=\"Has-text smwtype_txt\">abc</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgRestrictDisplayTitle": false
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0428.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0428.json
new file mode 100644
index 00000000..7f087050
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0428.json
@@ -0,0 +1,47 @@
+{
+ "description": "Test `_TYPE` annotations on different content language (`wgContLang=fr`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[A le type::Texte]]"
+ },
+ {
+ "page": "Example/P0428/1",
+ "contents": "[[Has text::#-Foo]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0428/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_text"
+ ],
+ "propertyValues": [
+ "#-Foo"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "fr",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0429.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0429.json
new file mode 100644
index 00000000..e87534a3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0429.json
@@ -0,0 +1,189 @@
+{
+ "description": "Test in-text `_dat` annotation with time offset, time zone, am/pm (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0429/1",
+ "contents": "[[Has date::1 Jan 1971 13:45:23-3:30]]"
+ },
+ {
+ "page": "Example/P0429/Q.1",
+ "contents": "{{#show: Example/P0429/1 |?Has date }}"
+ },
+ {
+ "page": "Example/P0429/2",
+ "contents": "[[Has date::1 Jan 1971 13:45:23 EST]]"
+ },
+ {
+ "page": "Example/P0429/Q.2",
+ "contents": "{{#show: Example/P0429/2 |?Has date }} {{#show: Example/P0429/2 |?Has date#LOCL#TZ }}"
+ },
+ {
+ "page": "Example/P0429/3",
+ "contents": "[[Has date::1 Jan 1971 13:45:23 am]]"
+ },
+ {
+ "page": "Example/P0429/4",
+ "contents": "[[Has date::1 Jan 1971 5:05:23 pm]]"
+ },
+ {
+ "page": "Example/P0429/5",
+ "contents": "[[Has date::1 Jan 1971 13:45:23 America/New_York]]"
+ },
+ {
+ "page": "Example/P0429/Q.5.1",
+ "contents": "{{#show: Example/P0429/5 |?Has date#LOCL#TZ }}"
+ },
+ {
+ "page": "Example/P0429/Q.5.2",
+ "contents": "{{#show: Example/P0429/5 |?Has date#LOCL#TZ@ja }}"
+ },
+ {
+ "page": "Example/P0429/Q.5.3",
+ "contents": "{{#show: Example/P0429/5 |?Has date#LOCL@ja#TZ }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 timeoffset",
+ "subject": "Example/P0429/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_date"
+ ],
+ "propertyValues": [
+ "1971-01-01T16:15:23"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0429/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "1 January 1971 16:15:23"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 timezone",
+ "subject": "Example/P0429/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_date"
+ ],
+ "propertyValues": [
+ "1971-01-01T18:45:23"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0429/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "1 January 1971 18:45:23",
+ "13:45:23 EST, 1 January 1971"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 invalid am/pm",
+ "subject": "Example/P0429/3",
+ "assert-output": {
+ "to-contain": [
+ "&quot;1 Jan 1971 13:45:23 am&quot; contains &quot;13&quot; as hour element that is invalid for a 12-hour convention."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 valid am/pm",
+ "subject": "Example/P0429/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_date"
+ ],
+ "propertyValues": [
+ "1971-01-01T17:05:23"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 valid am/pm",
+ "subject": "Example/P0429/4",
+ "assert-output": {
+ "to-contain": [
+ "1 Jan 1971 5:05:23 pm"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 long timezone name",
+ "subject": "Example/P0429/Q.5.1",
+ "assert-output": {
+ "to-contain": [
+ "13:45:23 America/New_York, 1 January 1971"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 long timezone name",
+ "subject": "Example/P0429/Q.5.2",
+ "assert-output": {
+ "to-contain": [
+ "1971年1月1日 (金) 13:45:23 America/New_York"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 long timezone name",
+ "subject": "Example/P0429/Q.5.3",
+ "assert-output": {
+ "to-contain": [
+ "1971年1月1日 (金) 13:45:23 America/New_York"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0430.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0430.json
new file mode 100644
index 00000000..45ccdcc9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0430.json
@@ -0,0 +1,133 @@
+{
+ "description": "Test in-text annotation for `_eid` type (`#nowiki`) (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "NDL ID",
+ "contents": "[[Has type::External identifier]] [[External formatter uri::https://id.ndl.go.jp/auth/ndlna/$1]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Some ID",
+ "contents": "[[Has type::External identifier]] [[External formatter uri::https://example.org/$1]]"
+ },
+ {
+ "page": "Example/P0430/1",
+ "contents": "[[NDL ID::00564222]]"
+ },
+ {
+ "page": "Example/P0430/Q1.1",
+ "contents": "{{#ask: [[NDL ID::00564222]] |?NDL ID |link=none}}"
+ },
+ {
+ "page": "Example/P0430/Q1.2",
+ "contents": "{{#ask: [[NDL ID::00564222]] |?NDL ID }}"
+ },
+ {
+ "page": "Example/P0430/2",
+ "contents": "[[Some ID::W%D6LLEKLA01]]"
+ },
+ {
+ "page": "Example/P0430/Q2.1",
+ "contents": "{{#ask: [[Some ID::W%D6LLEKLA01]] |?Some ID }}"
+ },
+ {
+ "page": "Example/P0430/Q2.2",
+ "contents": "{{#ask: [[Some ID::W%D6LLEKLA01]] |?Some ID#nowiki }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0430/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "NDL_ID",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "00564222"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"plainlinks smw-eid\"><a rel=\"nofollow\" class=\"external text\" href=\"https://id.ndl.go.jp/auth/ndlna/00564222\">00564222</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (link=none)",
+ "subject": "Example/P0430/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"NDL-ID smwtype_eid\" data-sort-value=\"00564222\">00564222</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0430/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"NDL-ID smwtype_eid\" data-sort-value=\"00564222\"><span class=\"plainlinks smw-eid\"><a rel=\"nofollow\" class=\"external text\" href=\"https://id.ndl.go.jp/auth/ndlna/00564222\">00564222</a></span></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (decode,encode)",
+ "subject": "Example/P0430/2",
+ "assert-output": {
+ "to-contain": [
+ "<a rel=\"nofollow\" class=\"external text\" href=\"https://example.org/W%D6LLEKLA01\">W%D6LLEKLA01</a>"
+ ],
+ "not-contain": [
+ "<a rel=\"nofollow\" class=\"external text\" href=\"https://example.org/W%25D6LLEKLA01\">W%D6LLEKLA01</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4",
+ "subject": "Example/P0430/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"plainlinks smw-eid\"><a rel=\"nofollow\" class=\"external text\" href=\"https://example.org/W%D6LLEKLA01\">W%D6LLEKLA01</a></span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 #nowiki",
+ "subject": "Example/P0430/Q2.2",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"plainlinks smw-eid\">https&#58;//example.org/W%D6LLEKLA01</span>"
+ ],
+ "not-contain": [
+ "<span class=\"plainlinks smw-eid\"><a rel=\"nofollow\" class=\"external text\" href=\"https://example.org/W%D6LLEKLA01\">W%D6LLEKLA01</a></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0431.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0431.json
new file mode 100644
index 00000000..e9c1c1f0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0431.json
@@ -0,0 +1,84 @@
+{
+ "description": "Test in-text annotation `_rec` and `|+index` (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record",
+ "contents": "[[Has type::Record]] [[Has fields::Has text;Has number]] [[Has property description::Test@en]]"
+ },
+ {
+ "page": "Example/P0431/1",
+ "contents": "[[Has record::Foo;123]]"
+ },
+ {
+ "page": "Example/P0431/Q1.1",
+ "contents": "{{#ask: [[Has record::+]] |?Has record|+index=Has text}}"
+ },
+ {
+ "page": "Example/P0431/Q1.2",
+ "contents": "{{#ask: [[Has record::+]] |?Has record|+index=Has number|?Has record|+index=Has text}}"
+ },
+ {
+ "page": "Example/P0431/Q2.1",
+ "contents": "{{#ask: [[Has property description::Test@en]] |?Has property description|+index=Language code}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0431/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0431/1",
+ "<td class=\"Has-record smwtype_txt\">Foo</td>"
+ ],
+ "not-contain": [
+ "<td class=\"Has-record smwtype_num\" data-sort-value=\"123\">123</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0431/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0431/1",
+ "<td class=\"Has-record smwtype_txt\">Foo</td>",
+ "<td class=\"Has-record smwtype_num\" data-sort-value=\"123\">123</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0431/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "Property:Has record",
+ "<td class=\"Property-description smwtype&#95;_lcode\">en</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0432.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0432.json
new file mode 100644
index 00000000..e5dcaf64
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0432.json
@@ -0,0 +1,186 @@
+{
+ "description": "Test in-text annotation for `_ref_rec` type (#1808, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number with ref",
+ "contents": "[[Has type::Reference]] [[Has fields::Number;Date;URL]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has mlt with ref",
+ "contents": "[[Has type::Reference]] [[Has fields::Monolingual text;Date;Number]]"
+ },
+ {
+ "page": "Example/P0432/1",
+ "contents": "[[Has number with ref::123;1.1.2000;http://example.org]]"
+ },
+ {
+ "page": "Example/P0432/Q1.1",
+ "contents": "{{#ask: [[Has number with ref::123]] |?Has number with ref|+index=Date|?Has number with ref|+index=URL |link=none}}"
+ },
+ {
+ "page": "Example/P0432/2",
+ "contents": "{{#subobject: |Has number with ref=456;12-04-1637;http://example.org }}"
+ },
+ {
+ "page": "Example/P0432/Q2.1",
+ "contents": "{{#ask: [[Has number with ref::456]] |?Has number with ref|+index=Date|?Has number with ref|+index=URL |link=none}}"
+ },
+ {
+ "page": "Example/P0432/3",
+ "contents": "[[Has mlt with ref::Test@en;01.01.1800;123]] {{#subobject: |Has mlt with ref::テスト@ja;01.01.1800;456 }}"
+ },
+ {
+ "page": "Example/P0432/Q3.1",
+ "contents": "{{#ask: [[Has mlt with ref::?@en]] |?Has mlt with ref|+index=Monolingual text|?Has mlt with ref|+index=Number |link=none}}"
+ },
+ {
+ "page": "Example/P0432/4",
+ "contents": "[[Has number with ref:: {{#show: Example/P0432/1 |?Has number with ref |link=none }}]]"
+ },
+ {
+ "page": "Example/P0432/5",
+ "contents": "{{#subobject: Has number with ref=999;1.1.2000 12:00;http://example.org}} {{#subobject: Has number with ref=999;1.1.2000 13:00;http://example.org}}"
+ },
+ {
+ "page": "Example/P0432/Q5.1",
+ "contents": "{{#ask: [[Has number with ref::999]] |order=asc |link=none |format=list}}"
+ },
+ {
+ "page": "Example/P0432/Q5.2",
+ "contents": "{{#ask: [[Has number with ref::999]] |order=desc |link=none |format=list}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0432/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_number_with_ref",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "123;1 January 2000;http://example.org"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "123<span class=\"smw-reference smw-reference-indicator smw-highlighter smwttinline\" data-title=\"Reference\"",
+ "January 1, 2000",
+ "href=&quot;http://example.org&quot;&gt;http://example.org",
+ "title=\"Date: January 1, 2000, URL: http://example.org\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0432/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0432/1</td>",
+ "<td class=\"Has-number-with-ref smwtype_dat\" data-sort-value=\"2451544.5\">1 January 2000</td>",
+ "<td class=\"Has-number-with-ref smwtype_uri\"><a rel=\"nofollow\" class=\"external free\" href=\"http://example.org\">http://example.org</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0432/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0432/2#_7b5db4a4195b1843f9a25639c0d7ff5c</td>",
+ "<td class=\"Has-number-with-ref smwtype_dat\" data-sort-value=\"2319299.5\">4 December 1637</td>",
+ "<td class=\"Has-number-with-ref smwtype_uri\"><a rel=\"nofollow\" class=\"external free\" href=\"http://example.org\">http://example.org</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (Monolingual text, number index output)",
+ "subject": "Example/P0432/Q3.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0432/3</td>",
+ "<td class=\"Has-mlt-with-ref smwtype_mlt_rec\">Test (en)</td>",
+ "<td class=\"Has-mlt-with-ref smwtype_num\" data-sort-value=\"123\">123</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (#show + link=none)",
+ "subject": "Example/P0432/4",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "Has_number_with_ref",
+ "_SKEY",
+ "_MDAT",
+ "_ASK"
+ ],
+ "propertyValues": [
+ "123;?;?"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "123<span class=\"smw-reference smw-reference-indicator smw-highlighter smwttinline\" data-title=\"Reference\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (chronological order, asc)",
+ "subject": "Example/P0432/Q5.1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-output": {
+ "to-contain": [
+ ">Example/P0432/5#_1c26bb9aac2df0c73a22cacd64a2b56a<.*>Example/P0432/5#_f3d26f55b0c2b1edf58613dd875ba0e5<"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (chronological order, desc)",
+ "subject": "Example/P0432/Q5.2",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-output": {
+ "to-contain": [
+ ">Example/P0432/5#_f3d26f55b0c2b1edf58613dd875ba0e5<.*>Example/P0432/5#_1c26bb9aac2df0c73a22cacd64a2b56a<"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0433.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0433.json
new file mode 100644
index 00000000..f8fa2e76
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0433.json
@@ -0,0 +1,87 @@
+{
+ "description": "Test in-text annotation `::` with left pipe (#1747, `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0433/1",
+ "contents": "[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[File:Example.png|Bar::Foobar|link=Foo]]"
+ },
+ {
+ "page": "Example/P0433/2",
+ "contents": "{{#set:Has text=[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[File:Example.png|Bar::Foobar|link=Foo]] }}"
+ },
+ {
+ "page": "Example/P0433/Q.1",
+ "contents": "{{#ask: [[Example/P0433/2]] |?Has text |link=none}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 no annotation due to left pipe",
+ "subject": "Example/P0433/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_INST"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0433/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_text"
+ ],
+ "propertyValues": [
+ "[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[File:Example.png|Bar::Foobar|link=Foo]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0433/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"File:Example.png\">Caption</a>",
+ "title=\"File:Example.png\">Bar::Foobar</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_STRICT",
+ "SMW_PARSER_INL_ERROR",
+ "SMW_PARSER_HID_CATS"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0434.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0434.json
new file mode 100644
index 00000000..eb9c75b1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0434.json
@@ -0,0 +1,215 @@
+{
+ "description": "Test printrequest property chaining `|?Foo.Bar` (#1824, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has population",
+ "contents": "[[Has type::Reference]] [[Has fields::Number;Date;URL]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Capital of",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0434/1",
+ "contents": "[[Has population::123;1 Jan 1970;http://example.org/SomeSource]] {{#subobject:Has population=456;1 Jan 2000;http://example.org/SomeSource }} [[Category:P0434]]"
+ },
+ {
+ "page": "Example/P0434/Q1.1",
+ "contents": "{{#ask: [[Has population::+]] [[Category:P0434]] |?Has population.Number |link=none}} {{#ask: [[Has population::+]] [[Category:P0434]] |?Has population.Number |link=none |format=debug}}"
+ },
+ {
+ "page": "Example/P0434/Q1.2",
+ "contents": "{{#ask: [[Has population::+]] [[Category:P0434]] |?Has population.Date |link=none}}"
+ },
+ {
+ "page": "Example/P0434/2",
+ "contents": "[[Capital of::Example/P0434/1]] [[Located in::Example/P0434/3]] [[Category:City]] [[Category:P0434]]"
+ },
+ {
+ "page": "Example/P0434/Q2.1",
+ "contents": "{{#ask: [[Category:City]] [[Category:P0434]] |?Capital of.Has population.Number |link=none}}"
+ },
+ {
+ "page": "Example/P0434/3",
+ "contents": "[[Located in::Example/P0434/4]] [[Category:Country]] [[Category:P0434]]"
+ },
+ {
+ "page": "Example/P0434/Q3.1",
+ "contents": "{{#ask: [[Category:Country]] [[Category:P0434]] |?Located in.-Located in.-Located in.Capital of |link=subject }}"
+ },
+ {
+ "page": "Example/P0434/Q3.2",
+ "contents": "{{#ask: [[Category:Country]] [[Category:P0434]] |?Located in.-Located in.-Located in.Capital of=SomeOtherText |link=none }}"
+ },
+ {
+ "page": "Example/P0434/Q3.3",
+ "contents": "{{#ask: [[Category:Country]] [[Category:P0434]] |?Located in.-Located in.-Located in.Capital of.Has subobject.Has population.Number |link=none }}"
+ },
+ {
+ "page": "Example/P0434/4",
+ "contents": "{{#subobject:Has population=123;1 Jan 2000;http://example.org/SomeSource |@category=P0434-sort }} {{#subobject:Has population=456;1 Jan 1900;http://example.org/SomeSource |@category=P0434-sort}} {{#subobject:Has population=789;1 Jan 1999;http://example.org/SomeSource |@category=P0434-sort}}"
+ },
+ {
+ "page": "Example/P0434/Q4.1",
+ "contents": "{{#ask: [[Category:P0434-sort]] |?Has population.Date |sort=Has population.Date |order=asc |link=none}}"
+ },
+ {
+ "page": "Example/P0434/Q4.2",
+ "contents": "{{#ask: [[Category:P0434-sort]] |?Has population.Date |sort=Has population.Date |order=desc |link=none}}"
+ },
+ {
+ "page": "Example/P0434/Q4.3",
+ "contents": "{{#ask: [[Category:P0434-sort]] |?Has population.Date |sort=Has population.Date,Has population.Number |order=asc,desc |link=none}}"
+ },
+ {
+ "page": "Example/P0434/Q4.4",
+ "contents": "{{#ask: [[Category:P0434-sort]] |?Has population.Date |sort=Has population.Date,Has population.Number |order=desc,asc |link=none}}"
+ }
+
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0434/Q1.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0434/1</td><td class=\"Number smwtype_num\" data-sort-value=\"123\">123</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31-)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0434/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0434/1</td><td class=\"Date smwtype_dat\" data-sort-value=\"2440587.5\">1 January 1970</td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31+)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0434/Q1.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0434/1</td><td class=\"Date smwtype_dat\" data-sort-value=\"2440587.5\">1 January 1970</td></tr></tbody></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 on (?Capital of.Has population.Number)",
+ "subject": "Example/P0434/Q2.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0434/2</td><td class=\"Number smwtype_num\" data-sort-value=\"123\">123</td>"
+ ],
+ "not-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0434/1</td><td class=\"Number smwtype_num\" data-sort-value=\"123\">123</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 on (?Located in.-Located in.-Located in.Capital of)",
+ "subject": "Example/P0434/Q3.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Capital-of smwtype_wpg\">Example/P0434/1</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 on (?Located in.-Located in.-Located in.Capital of=SomeOtherText)",
+ "subject": "Example/P0434/Q3.2",
+ "assert-output": {
+ "to-contain": [
+ "SomeOtherText</a>&#160;<span title=\"Located in.-Located in.-Located in.Capital of\">â ‰</span>",
+ "<td class=\"SomeOtherText smwtype_wpg\">Example/P0434/1</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 on (?Located in.-Located in.-Located in.Capital of.Has subobject.Has population.Number)",
+ "subject": "Example/P0434/Q3.3",
+ "assert-output": {
+ "to-contain": [
+ "<span title=\"Located in.-Located in.-Located in.Capital of.Has subobject.Has population.Number\">â ‰</span>",
+ "<td class=\"smwtype_wpg\">Example/P0434/3</td><td class=\"Number smwtype_num\" data-sort-value=\"456\">456</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (sort=Has population.Date, order=asc) ",
+ "subject": "Example/P0434/Q4.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_357f4a06073b86afc07cb0c6237b9f36</td><td class=\"Date smwtype_dat\" data-sort-value=\"2415020.5\">1 January 1900</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0434/4#_eb1c9a9f3a8ad677d7424e8d842b10dd</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451179.5\">1 January 1999</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_4bae31c0cd5bda46c3cf0245523a954a</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451544.5\">1 January 2000</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 (sort=Has population.Date, order=desc) ",
+ "subject": "Example/P0434/Q4.2",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_4bae31c0cd5bda46c3cf0245523a954a</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451544.5\">1 January 2000</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0434/4#_eb1c9a9f3a8ad677d7424e8d842b10dd</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451179.5\">1 January 1999</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_357f4a06073b86afc07cb0c6237b9f36</td><td class=\"Date smwtype_dat\" data-sort-value=\"2415020.5\">1 January 1900</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 (Has population.Date,Has population.Number, order=asc,desc) ",
+ "subject": "Example/P0434/Q4.3",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_357f4a06073b86afc07cb0c6237b9f36</td><td class=\"Date smwtype_dat\" data-sort-value=\"2415020.5\">1 January 1900</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0434/4#_eb1c9a9f3a8ad677d7424e8d842b10dd</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451179.5\">1 January 1999</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_4bae31c0cd5bda46c3cf0245523a954a</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451544.5\">1 January 2000</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 (Has population.Date,Has population.Number, order=desc,asc) ",
+ "subject": "Example/P0434/Q4.4",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_4bae31c0cd5bda46c3cf0245523a954a</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451544.5\">1 January 2000</td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\">Example/P0434/4#_eb1c9a9f3a8ad677d7424e8d842b10dd</td><td class=\"Date smwtype_dat\" data-sort-value=\"2451179.5\">1 January 1999</td></tr>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0434/4#_357f4a06073b86afc07cb0c6237b9f36</td><td class=\"Date smwtype_dat\" data-sort-value=\"2415020.5\">1 January 1900</td></tr>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0435.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0435.json
new file mode 100644
index 00000000..60132ae3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0435.json
@@ -0,0 +1,66 @@
+{
+ "description": "Test in-text annotation using `_txt` type with 255+ char, `#ask` to produce reduced length (#1878, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0435/1",
+ "contents": "[[Has text::TBgcHiQBTvpV3XkFiRpMcV1KQoZvQXFyiQUQMM2RoYUyJaRoSyKnsQTWwia3HATd4YVmd8BZgkL2LfL0Q6rP5E90A\\4IuV6u/KdYjL3nxZvx0pbc3tbxwa6jMW1JDNxusaKQ52ftRS7DCEY1IPTRZnuRMLPgWYwLOsEAebOsxD7BBL9IK3Z2Osfh9s0FC1SUwCVdKcLkBgurXKGi99s61qnAU2zWFXBUCEzID6533LeaHCBKW8i2BgTK2tv65LHO6zB:;%&`^WithTextLongerThan255]]"
+ },
+ {
+ "page": "Example/P0435/Q.1",
+ "contents": "{{#ask: [[Example/P0435/1]] |?Has text#20 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0435/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_text",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "TBgcHiQBTvpV3XkFiRpMcV1KQoZvQXFyiQUQMM2RoYUyJaRoSyKnsQTWwia3HATd4YVmd8BZgkL2LfL0Q6rP5E90A\\4IuV6u/KdYjL3nxZvx0pbc3tbxwa6jMW1JDNxusaKQ52ftRS7DCEY1IPTRZnuRMLPgWYwLOsEAebOsxD7BBL9IK3Z2Osfh9s0FC1SUwCVdKcLkBgurXKGi99s61qnAU2zWFXBUCEzID6533LeaHCBKW8i2BgTK2tv65LHO6zB:;%&`^WithTextLongerThan255"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "TBgcHiQBTvpV3XkFiRpMcV1KQoZvQXFyiQUQMM2RoYUyJaRoSyKnsQTWwia3HATd4YVmd8BZgkL2LfL0Q6rP5E90A\\4IuV6u/KdYjL3nxZvx0pbc3tbxwa6jMW1JDNxusaKQ52ftRS7DCEY1IPTRZnuRMLPgWYwLOsEAebOsxD7BBL9IK3Z2Osfh9s0FC1SUwCVdKcLkBgurXKGi99s61qnAU2zWFXBUCEzID6533LeaHCBKW8i2BgTK2tv65LHO6zB:;%&amp;`^WithTextLongerThan255"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0435/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">TBgcHiQBTvpV3XkFiRpM …</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0436.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0436.json
new file mode 100644
index 00000000..b591c343
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0436.json
@@ -0,0 +1,114 @@
+{
+ "description": "Test in-text annotation with `_PPLB` [preferred property label] (#1879, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "P106",
+ "contents": {
+ "import-from": "/../Fixtures/P106.txt"
+ }
+ },
+ {
+ "page": "Example/P0436/1",
+ "contents": "{{#subobject: |P106=Teacher }}{{#subobject: |P106=Actor }}"
+ },
+ {
+ "page": "Example/P0436/Q.1",
+ "contents": "{{#ask: [[P106::+]] |?P106 }}"
+ },
+ {
+ "page": "Example/P0436/Q.2",
+ "contents": "{{#ask: [[P106::+]] |?P106 |headers=plain }}"
+ },
+ {
+ "page": "Example/P0436/Q.3",
+ "contents": "{{#ask: [[P106::+]] |?P106=with a different Label |headers=plain }}"
+ },
+ {
+ "page": "Example/P0436/Q.4",
+ "contents": "{{#ask: [[P106::+]] |?P106=with a different Label }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "P106",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 6,
+ "propertyKeys": [
+ "_PPLB",
+ "_PDESC",
+ "_TYPE",
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#0 (en)",
+ "subject": "Example/P0436/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "data-title=\"Property\" title=\"occupation of a person; see also field of work (Property:P101)\">",
+ "title=\"Property:P106\">occupation</a>",
+ "<span class=\"smwttcontent\">occupation of a person; see also field of work (Property:P101)</span></span>&#160;<span title=\"P106\"><sup>áµ–</sup></span>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (en, headers=plain)",
+ "subject": "Example/P0436/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"occupation\">occupation</th>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (en, headers=plain, different label)",
+ "subject": "Example/P0436/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"with-a-different-Label\">with a different Label</th>"
+ ],
+ "not-contain": [
+ "<th class=\"occupation\">occupation</th>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (en, different label, doesn't contain a prefLabel marker)",
+ "subject": "Example/P0436/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"with-a-different-Label\">",
+ "title=\"Property:P106\">with a different Label</a>",
+ "<span class=\"smwttcontent\">occupation of a person; see also field of work (Property:P101)</span></span>"
+ ],
+ "not-contain": [
+ "<th class=\"occupation\">occupation</th>",
+ "&#160;<span title=\"P106\"><sup>áµ–</sup></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0437.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0437.json
new file mode 100644
index 00000000..9f5588df
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0437.json
@@ -0,0 +1,42 @@
+{
+ "description": "Test in-text annotation with preferred property label/`_PPLB` (#1879, `wgContLang=en`, `wgLang=ja`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "P106",
+ "contents": {
+ "import-from": "/../Fixtures/P106.txt"
+ }
+ },
+ {
+ "page": "Example/P0437/1",
+ "contents": "{{#subobject: |P106=Teacher }}{{#subobject: |P106=Actor }}"
+ },
+ {
+ "page": "Example/P0437/Q.1",
+ "contents": "{{#ask: [[P106::+]] |?P106 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (ja)",
+ "subject": "Example/P0437/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "data-title=\"プロパティ\" title=\"人物ã®è·æ¥­ã€‚「専門分野ã€(Property:P101) ã‚‚å‚ç…§\">",
+ "title=\"Property:P106\">è·æ¥­</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "ja"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0438.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0438.json
new file mode 100644
index 00000000..38918bc2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0438.json
@@ -0,0 +1,61 @@
+{
+ "description": "Test in-text annotation with preferred property label/DISPLAYTITLE on user/predefined properties (`wgContLang=es`, `wgLang=de`, `wgRestrictDisplayTitle=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Modification date",
+ "contents": "[[Has preferred property label::prefLabel-123@de]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has query",
+ "contents": "{{DISPLAYTITLE:query-displaytitle}}"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has keyword",
+ "contents": "[[Has preferred property label::prefLabel-456@de]]"
+ },
+ {
+ "page": "Example/P0438/1",
+ "contents": "[[Category:P0438]] [[Has keyword::some keyword]]"
+ },
+ {
+ "page": "Example/P0438/2",
+ "contents": "[[Category:P0438]] [[Has keyword::another keyword]]"
+ },
+ {
+ "page": "Example/P0438/Q.1",
+ "contents": "{{#ask: [[Category:P0438]] |?Modification date |?Modification date=ModificationSomeLabel |?Has keyword |?Has keyword=KeywordCaption |?Has query |?Has query=QueryCaption |limit=1 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (combination of prefLabel, DISPLAYTITLE, local caption)",
+ "subject": "Example/P0438/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:Modification date\">prefLabel-123</a></span><span class=\"smwttcontent\">„prefLabel-123&#160;<span style=\"font-size:small;\">(Modification date)</span>“",
+ "title=\"Property:Modification date\">ModificationSomeLabel</a></span><span class=\"smwttcontent\">„prefLabel-123&#160;<span style=\"font-size:small;\">(Modification date)</span>“",
+ "&#160;<span title=\"Modification date\"><sup>áµ–</sup></span>",
+ "title=\"Property:Has keyword\">prefLabel-456</a>&#160;<span title=\"Has keyword\"><sup>áµ–</sup>",
+ "title=\"Property:Has keyword\">KeywordCaption</a>",
+ "title=\"Property:Has query\">query-displaytitle</a></span><span class=\"smwttcontent\">„query-displaytitle&#160;<span style=\"font-size:small;\">(Has query)</span>“",
+ "title=\"Property:Has query\">QueryCaption</a></span><span class=\"smwttcontent\">„query-displaytitle&#160;<span style=\"font-size:small;\">(Has query)</span>“",
+ ":Ask/-5B-5BCategoría:P0438-5D-5D/-3FModification-20date/-3FModification-20date=ModificationSomeLabel/-3FHas-20keyword/-3FHas-20keyword=KeywordCaption/-3FHas-20query/-3FHas-20query=QueryCaption/mainlabel=/limit=1/offset=1/format=table\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "es",
+ "wgLang": "de",
+ "wgRestrictDisplayTitle": false
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0439.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0439.json
new file mode 100644
index 00000000..311217e8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0439.json
@@ -0,0 +1,122 @@
+{
+ "description": "Test in-text annotation using '_txt'/'_wpg' type / UTF encoding (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0439/1",
+ "contents": "[[Has text::ö/ä/ü]]"
+ },
+ {
+ "page": "Example/P0439/2",
+ "contents": {
+ "import-from": "/../Fixtures/p-0439.de.txt"
+ }
+ },
+ {
+ "page": "Example/P0439/3",
+ "contents": {
+ "import-from": "/../Fixtures/p-0439.fr.txt"
+ }
+ },
+ {
+ "page": "Example/P0439/ö/ä/ü",
+ "contents": "[[Has page::Some ö/ä/ü]]"
+ },
+ {
+ "page": "Example/P0439/Q.1",
+ "contents": "{{#ask: [[Has text::ö/ä/ü]] |?Has text }}"
+ },
+ {
+ "page": "Example/P0439/Q.2",
+ "contents": "{{#ask: [[Example/P0439/2]] |?Has text }}"
+ },
+ {
+ "page": "Example/P0439/Q.3",
+ "contents": "{{#ask: [[Example/P0439/3]] |?Has text }}"
+ },
+ {
+ "page": "Example/P0439/Q.4",
+ "contents": "{{#ask: [[Has page::Some ö/ä/ü]] |?Has page }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0439/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_text",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "ö/ä/ü"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0439/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">ö/ä/ü</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (long text, de)",
+ "subject": "Example/P0439/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "fügte, während ihr Gesicht sich aufklärte"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (long text, fr)",
+ "subject": "Example/P0439/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "nous avons annoncé le chef-d'oeuvre du poëte"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4",
+ "subject": "Example/P0439/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0439/ö/ä/ü\">Example/P0439/ö/ä/ü</a>",
+ "Some ö/ä/ü"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0440.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0440.json
new file mode 100644
index 00000000..b2769e58
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0440.json
@@ -0,0 +1,187 @@
+{
+ "description": "Test in-text annotation `_mlt_rec` (Monolingual text) with `|+lang`/`|+order` parameter (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has alternative label",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "SomeProperty",
+ "contents": " [[Category:P0440]] [[Has property description::Something ...@en]] [[Has property description::何ã‹ã‚ã‚‹ã‚‚ã®ã€‚。。@ja]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "AnotherProperty",
+ "contents": " [[Category:P0440]] [[Has property description::Something else ...@en]] [[Has property description::ä»–ã®ä½•ã‹ã‚ã‚‹ã‚‚ã®ã€‚。。@ja]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has alternative record",
+ "contents": "[[Has type::Record]] [[Has fields::Text;Number]]"
+ },
+ {
+ "page": "Example/P0440/Triacylglycerol lipase",
+ "contents": "[[Has page::{{FULLPAGENAME}}]] [[Has alternative record::ABC;123]] [[Has alternative label::Lipase@en]], [[Has alternative label::Tributyrase@en]], [[Has alternative label::Triglyceride lipase@en]], [[Has alternative label::トリアシルグリセロールリパーゼ@ja]], [[Has alternative label::ليباز ثلاثي اسيل الغليسيرول@ar]], [[Has alternative label::Triacylglycérol lipase@fr]], [[Has alternative label::Triacilglicerol lipaza@sh]], [[Has alternative label::Triacilglicerol lipaza@sr]]"
+ },
+ {
+ "page": "Example/P0440/Q.0",
+ "contents": "{{#ask: [[Has alternative label::+]] |?Has alternative label|+order=desc }}"
+ },
+ {
+ "page": "Example/P0440/Q.1",
+ "contents": "{{#ask: [[Has alternative label::+]] |?Has alternative label|+order=asc }}"
+ },
+ {
+ "page": "Example/P0440/Q.2",
+ "contents": "{{#ask: [[Has alternative label::+]] |?Has alternative label|+lang=en|+order=asc }}"
+ },
+ {
+ "page": "Example/P0440/Q.3",
+ "contents": "{{#ask: [[Has alternative label::+]] |?Has alternative label|+lang=en|+limit=1|+order=asc }}"
+ },
+ {
+ "page": "Example/P0440/Q.4",
+ "contents": "{{#ask: [[Has alternative label::+]] |?Has alternative label|+lang=en|+limit=1 |limit=0 }}"
+ },
+ {
+ "page": "Example/P0440/Q.5",
+ "contents": "{{#ask: [[Has alternative label::+]] |?Has alternative label|+lang=foo|+order=asc }}"
+ },
+ {
+ "page": "Example/P0440/Q.6",
+ "contents": "{{#ask: [[Has alternative label::+]] |?Has page|+lang=en }}"
+ },
+ {
+ "page": "Example/P0440/Q.7",
+ "contents": "{{#ask: [[Has alternative record::+]] |?Has alternative record|+lang=en }}"
+ },
+ {
+ "page": "Example/P0440/Q.8",
+ "contents": "{{#ask: [[Category:P0440]] [[Has property description::+]] |?Has property description|+lang=en }}"
+ },
+ {
+ "page": "Example/P0440/Q.9",
+ "contents": "{{#ask: [[Category:P0440]] [[Has property description::+]] |?Has property description|+lang=en |?Has property description|+lang=ja |limit=1 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (no filter, lang tag, desc)",
+ "subject": "Example/P0440/Q.0",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-alternative-label smwtype_mlt_rec\">トリアシルグリセロールリパーゼ (ja)<br />ليباز ثلاثي اسيل الغليسيرول (ar)<br />Triglyceride lipase (en)<br />Tributyrase (en)<br />Triacylglycérol lipase (fr)<br />Triacilglicerol lipaza (sr)<br />Triacilglicerol lipaza (sh)<br />Lipase (en)</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (no filter, lang tag, asc)",
+ "subject": "Example/P0440/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-alternative-label smwtype_mlt_rec\">Lipase (en)<br />Triacilglicerol lipaza (sh)<br />Triacilglicerol lipaza (sr)<br />Triacylglycérol lipase (fr)<br />Tributyrase (en)<br />Triglyceride lipase (en)<br />ليباز ثلاثي اسيل الغليسيرول (ar)<br />トリアシルグリセロールリパーゼ (ja)</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (filtered by language, no lang tag)",
+ "subject": "Example/P0440/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-alternative-label smwtype_txt\">Lipase<br />Tributyrase<br />Triglyceride lipase</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (column value list limited to 1)",
+ "subject": "Example/P0440/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-alternative-label smwtype_txt\">Lipase</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (no result, Special:Ask link)",
+ "subject": "Example/P0440/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "-5B-5BHas-20alternative-20label::+-5D-5D/-3FHas-20alternative-20label-7C+lang=en-7C+limit=1/mainlabel=/offset=0/format=table"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (invalid/unknown/unmatchable language)",
+ "subject": "Example/P0440/Q.5",
+ "assert-output": {
+ "not-contain": [
+ "<td class=\"Has-alternative-label smwtype_txt\">Lipase<br />Tributyrase<br />Triglyceride lipase</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (+lang not applied on non-Monolingual type)",
+ "subject": "Example/P0440/Q.6",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0440/Triacylglycerol lipase\">Example/P0440/Triacylglycerol lipase</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 (+lang not applied on non-Monolingual type)",
+ "subject": "Example/P0440/Q.7",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0440/Triacylglycerol lipase\">Example/P0440/Triacylglycerol lipase</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8",
+ "subject": "Example/P0440/Q.8",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Property-description smwtype_txt\">Something else ...</td>",
+ "<td class=\"Property-description smwtype_txt\">Something ...</td>"
+ ],
+ "not-contain": [
+ "<td class=\"Property-description smwtype_txt\">Something ...<br />何ã‹ã‚ã‚‹ã‚‚ã®ã€‚。。</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#9 (no `|+index=...` in further result links)",
+ "subject": "Example/P0440/Q.9",
+ "assert-output": {
+ "to-contain": [
+ "-5B-5BCategory:P0440-5D-5D-20-5B-5BProperty-20description::+-5D-5D/-3FProperty-20description-7C+lang=en/-3FProperty-20description-7C+lang=ja/mainlabel=/limit=1/offset=1/format=table"
+ ],
+ "not-contain": [
+ "-5B-5BCategory:P0440-5D-5D-20-5B-5BProperty-20description::+-5D-5D/-3FProperty-20description-7C+lang=en-7C+index=1/-3FProperty-20description-7C+lang=ja-7C+index=1/mainlabel=/limit=1/offset=1/format=table"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0441.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0441.json
new file mode 100644
index 00000000..2d80061b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0441.json
@@ -0,0 +1,47 @@
+{
+ "description": "Test in-text `_txt` 00 string/loose comparison (#2061)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0441/1",
+ "contents": "[[Has text::011]] [[Has text::0011]]"
+ },
+ {
+ "page": "Example/P0441/1",
+ "contents": "[[Has text::011]] [[Has text::00011]]"
+ },
+ {
+ "page": "Example/P0441/2",
+ "contents": "{{#ask: [[Example/P0441/1]] |?Has text }}",
+ "message-cache": "clear"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0441/2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\" data-sort-value=\"011\">011<br />00011</td>"
+ ],
+ "no-contain": [
+ "<td class=\"Has-text smwtype_txt\" data-sort-value=\"011\">011</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0442.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0442.json
new file mode 100644
index 00000000..87edf58b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0442.json
@@ -0,0 +1,50 @@
+{
+ "description": "Test in-text `#REDIRECT` to verify target subobject isn't removed (#, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]] [[Has property description::Some text that should remain@en]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has another text",
+ "contents": "#REDIRECT [[Property:Has text]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (verify redirect doesn't delete the subobjects of a target; if it fails then propertyValues will be empty and cause an error in this test)",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has text",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_PDESC",
+ "_TYPE"
+ ],
+ "propertyValues": [
+ "Some text that should remain@en"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0443.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0443.json
new file mode 100644
index 00000000..b7897824
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0443.json
@@ -0,0 +1,198 @@
+{
+ "description": "Test conditions and strict constraint validations for uniqueness `_PVUC` on `_txt`/`_rec`/`_ref_rec` with unique field (#1463, #3547, `smwgDVFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has uniqueness one",
+ "contents": "[[Has type::Text]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has uniqueness two",
+ "contents": "[[Has type::Text]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Unique field",
+ "contents": "[[Has type::Text]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Another unique field",
+ "contents": "[[Has type::Text]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Unique record",
+ "contents": "[[Has type::Record]] [[Has fields::Unique field;Non unique field]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Unique reference",
+ "contents": "[[Has type::Reference]] [[Has fields::Unique field;Another unique field;Non unique field]]"
+ },
+ {
+ "page": "Example/P0443/1",
+ "contents": "[[Has uniqueness one::Allowed one]] [[Has uniqueness one::Not permitted]] [[Has uniqueness two::Allowed two]] [[Has uniqueness two::Not permitted]]"
+ },
+ {
+ "page": "Example/P0443/2",
+ "contents": "[[Has uniqueness one::1111]] {{#ask: [[Has uniqueness one::1111]] |link=none |format=plainlist}}"
+ },
+ {
+ "page": "Example/P0443/3",
+ "contents": "[[Unique record::abc;123]]"
+ },
+ {
+ "page": "Example/P0443/4",
+ "contents": "[[Unique record::abc;123]] (fails on abc)"
+ },
+ {
+ "page": "Example/P0443/5",
+ "contents": "[[Unique reference::abc;def;123]] (fails on abc)"
+ },
+ {
+ "page": "Example/P0443/6",
+ "contents": "[[Unique reference::abcd;def;123]]"
+ },
+ {
+ "page": "Example/P0443/7",
+ "contents": "[[Unique reference::abcde;def;123]] (fails on def)"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (verify uniqueness for only one assignment per property)",
+ "subject": "Example/P0443/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ERRC",
+ "Has uniqueness one",
+ "Has uniqueness two"
+ ],
+ "propertyValues": [
+ "Allowed one",
+ "Allowed two"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (verify declared unique value doesn't interfere with #ask within the same page)",
+ "subject": "Example/P0443/2",
+ "assert-output": {
+ "to-contain": [
+ "<p>1111 Example/P0443/2"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (verify uniqueness of field in record )",
+ "subject": "Example/P0443/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "Unique record"
+ ],
+ "propertyValues": [
+ "abc; 123"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (verify uniqueness of field in record fails for same value as used in Example/P0443/3)",
+ "subject": "Example/P0443/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (verify uniqueness of field in reference fails for same value as used in Example/P0443/3)",
+ "subject": "Example/P0443/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (verify uniqueness for reference with uniqueness fields)",
+ "subject": "Example/P0443/6",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "Unique reference"
+ ],
+ "propertyValues": [
+ "abcd"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (verify uniqueness of field in reference fails for same value as used in Example/P0443/6)",
+ "subject": "Example/P0443/7",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ERRC"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "smwgDVFeatures": [
+ "SMW_DV_PVUC"
+ ],
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0444.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0444.json
new file mode 100644
index 00000000..502f2542
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0444.json
@@ -0,0 +1,207 @@
+{
+ "description": "Test in-text annotation with links in values (#2153, `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0444/1",
+ "contents": {
+ "import-from": "/../Fixtures/p-0444.txt"
+ }
+ },
+ {
+ "page": "Example/P0444/2",
+ "contents": "[[Has text::[[Lorem ipsum]][[Lorem ipsum|Bar]]]]"
+ },
+ {
+ "page": "Example/P0444/3",
+ "contents": "[[Has text::[http://example.org/eleifend eleifend]]]"
+ },
+ {
+ "page": "Example/P0444/4",
+ "contents": "[[Has text::[[Has number::42|1001]]]] [[Category:P0444]]"
+ },
+ {
+ "page": "Example/P0444/Q.1",
+ "contents": "{{#ask: [[Category:P0444]] |format=embedded }}"
+ },
+ {
+ "page": "Example/P0444/5",
+ "contents": "[[Has text::[[:Lorem ipsum]] [[:Lorem ipsum|Bar]]]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 import",
+ "subject": "Example/P0444/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 6,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has page",
+ "Has number",
+ "Has date",
+ "Has text"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 internal wiki link",
+ "subject": "Example/P0444/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "[[Lorem ipsum]][[Lorem ipsum|Bar]]"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">Lorem ipsum</a>",
+ ">Bar</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 external link",
+ "subject": "Example/P0444/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "[http://example.org/eleifend eleifend]"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">eleifend</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 link-in annotation (piped hence annotated 42, displayed 1001)",
+ "subject": "Example/P0444/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_INST",
+ "Has text",
+ "Has number"
+ ],
+ "propertyValues": [
+ "42"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "1001"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 embbeded format to verify that [[SMW::OFF]]/[[SMW:ON]] remains intact after transclusion",
+ "subject": "Example/P0444/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ASK"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 internal wiki link (`[[:...`)",
+ "subject": "Example/P0444/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "[[:Lorem ipsum]] [[:Lorem ipsum|Bar]]"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">Lorem ipsum</a>",
+ ">Bar</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_STRICT",
+ "SMW_PARSER_INL_ERROR",
+ "SMW_PARSER_HID_CATS",
+ "SMW_PARSER_LINV"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0445.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0445.json
new file mode 100644
index 00000000..9b8f5884
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0445.json
@@ -0,0 +1,63 @@
+{
+ "description": "Test in-text annotation for `_ref_rec` type with errors (#..., `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number reference",
+ "contents": "[[Has type::Reference]] [[Has fields::Number;Date]]"
+ },
+ {
+ "page": "Example/P0445/1",
+ "contents": "[[Has number reference::Foo;1 Jan 1970]]"
+ },
+ {
+ "page": "Example/P0445/2",
+ "contents": "[[Has number reference::123;Foo]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 error on number element (type mismatch)",
+ "subject": "Example/P0445/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 error on date element (type mismatch)",
+ "subject": "Example/P0445/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0446.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0446.json
new file mode 100644
index 00000000..0820df6f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0446.json
@@ -0,0 +1,257 @@
+{
+ "description": "Test in-text annotation `_uri`/`_ema`/`_tel` with spaces/underscore (`wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has telephone number",
+ "contents": "[[Has type::Telephone number]]"
+ },
+ {
+ "page": "Example/P0446/1",
+ "contents": "[[Has url::http://example.org/Foo bar]] [[Has url::http://example.org/Foo%20bar]] [[Has url::http://example.org/Foo_bar]] [[Category:P0446]]"
+ },
+ {
+ "page": "Example/P0446/Q.1.0",
+ "contents": "{{#ask: [[Has url::http://example.org/Foo bar]] [[Category:P0446]] |?Has url }}"
+ },
+ {
+ "page": "Example/P0446/Q.1.1",
+ "contents": "{{#ask: [[Has url::http://example.org/Foo bar]] [[Category:P0446]] |?Has url |link=none }}"
+ },
+ {
+ "page": "Example/P0446/2",
+ "contents": "[[Has url::http://example.org/Foo bar|Foo bar]] [[Has url::http://example.org/Foo_bar|Foo bar]] __SHOWFACTBOX__"
+ },
+ {
+ "page": "Example/P0446/3",
+ "contents": "[[Email::john_doe@example.org]]"
+ },
+ {
+ "page": "Example/P0446/Q.3",
+ "contents": "{{#ask: [[Email::john_doe@example.org]] |?Email }}"
+ },
+ {
+ "page": "Example/P0446/4",
+ "contents": "[[Has telephone number::+1 201 555 5555]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 spaces (_, , %20) produce only one URL not three",
+ "subject": "Example/P0446/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_INST",
+ "Has url"
+ ],
+ "propertyValues": [
+ "http://example.org/Foo_bar"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "href=\"http://example.org/Foo_bar\">http://example.org/Foo bar</a>",
+ "href=\"http://example.org/Foo_bar\">http://example.org/Foo%20bar</a>",
+ "href=\"http://example.org/Foo_bar\">http://example.org/Foo bar</a>"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 different space encoding dont't disort the condition/result",
+ "condition": "[[Has url::http://example.org/Foo bar]] [[Category:P0446]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Example/P0446/1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has url",
+ "value": "http://example.org/Foo_bar"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (same as #1)",
+ "condition": "[[Has url::http://example.org/Foo_bar]] [[Category:P0446]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Example/P0446/1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has url",
+ "value": "http://example.org/Foo_bar"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (same as #1)",
+ "condition": "[[Has url::http://example.org/Foo%20bar]] [[Category:P0446]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Example/P0446/1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has url",
+ "value": "http://example.org/Foo_bar"
+ }
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 #ask output (url with underscore)",
+ "subject": "Example/P0446/Q.1.0",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_uri\"><a rel=\"nofollow\" class=\"external text\" href=\"http://example.org/Foo_bar\">http://example.org/Foo bar</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 #ask output (url with underscore + link=none)",
+ "subject": "Example/P0446/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_uri\"><a rel=\"nofollow\" class=\"external free\" href=\"http://example.org/Foo_bar\">http://example.org/Foo_bar</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6",
+ "subject": "Example/P0446/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has url"
+ ],
+ "propertyValues": [
+ "http://example.org/Foo_bar"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "href=\"http://example.org/Foo_bar\">Foo bar</a>"
+ ],
+ "not-contain": [
+ "href=\"http://example.org/Foo_bar\">http://example.org/Foo bar</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 (email with underscore)",
+ "subject": "Example/P0446/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ema"
+ ],
+ "propertyValues": [
+ "john_doe@example.org"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "href=\"mailto:john_doe@example.org\">john_doe@example.org</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 #ask output (email with underscore)",
+ "subject": "Example/P0446/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "href=\"mailto:john_doe@example.org\">john_doe@example.org</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 (tel with blank spaces)",
+ "subject": "Example/P0446/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has telephone number"
+ ],
+ "propertyValues": [
+ "+1-201-555-5555"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "href=\"tel:+1-201-555-5555\">+1 201 555 5555</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0447.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0447.json
new file mode 100644
index 00000000..571d7ba8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0447.json
@@ -0,0 +1,78 @@
+{
+ "description": "Test in-text annotation with IRI export (#2188, `smwgExportResourcesAsIri=true`, `wgContLang=ru`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Заголовок",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Тип публикации",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Журнал",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Год",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0447/1",
+ "contents": "[[Заголовок::Pollen Limitation]] [[Журнал::Arctic, Antarctic and Alpine Research]] [[Год::2009]] [[Тип публикации::СтатьÑ]]"
+ },
+ {
+ "page": "Example/P0447/Q.1.1",
+ "contents": "{{#ask: [[Заголовок::Pollen Limitation]] |?Заголовок }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0447/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 6,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Заголовок",
+ "Журнал",
+ "Год",
+ "Тип публикации"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0447/Q.1.1",
+ "assert-output": {
+ "to-contain": [
+ "Property:%D0%97%D0%B0%D0%B3%D0%BE%D0%BB%D0%BE%D0%B2%D0%BE%D0%BA\" title=\"Property:Заголовок\">Заголовок</a>",
+ "Pollen Limitation</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "ru",
+ "wgLang": "en",
+ "smwgExportResourcesAsIri": true,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0448.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0448.json
new file mode 100644
index 00000000..1a575457
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0448.json
@@ -0,0 +1,74 @@
+{
+ "description": "Test in-text legacy `:=` annotation style (#2153, `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0448/1",
+ "contents": "[[Has text:=Lorem ipsum]]"
+ },
+ {
+ "page": "Example/P0448/2",
+ "contents": "[[Has text::==Lorem ipsum==]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0448/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "Lorem ipsum"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0448/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "==Lorem ipsum=="
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_STRICT",
+ "SMW_PARSER_INL_ERROR",
+ "SMW_PARSER_HID_CATS"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0449.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0449.json
new file mode 100644
index 00000000..7b7f24d1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0449.json
@@ -0,0 +1,156 @@
+{
+ "description": "Test in-text legacy `:=` and `::` annotation style with enabled links in values (#2153, `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0449/2",
+ "contents": "[[Has text:=[[Lorem ipsum]]]]"
+ },
+ {
+ "page": "Example/P0449/3",
+ "contents": "[[Has text:=[http://example.org/eleifend eleifend]]] [[Has text::[http://example.org/eleifend eleifend]]]"
+ },
+ {
+ "page": "Example/P0449/4",
+ "contents": "[[Has text:=[[Has number:=42]] [[Has number::1001]]]] [[Category:P0449]]"
+ },
+ {
+ "page": "Example/P0449/Q.1",
+ "contents": "{{#ask: [[Category:P0449]] |format=embedded }}"
+ }
+ ],
+ "tests": [
+
+ {
+ "type": "parser",
+ "about": "#1 internal wiki link",
+ "subject": "Example/P0449/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "[[Lorem ipsum]]"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">Lorem ipsum</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 external link",
+ "subject": "Example/P0449/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "[http://example.org/eleifend eleifend]"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">eleifend</a>"
+ ],
+ "not-contain": [
+ "[[Has text::<a rel=\"nofollow\" class=\"external text\" href=\"http://example.org/eleifend\">eleifend</a>]]"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 link-in annotation",
+ "subject": "Example/P0449/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_INST",
+ "Has text",
+ "Has number"
+ ],
+ "propertyValues": [
+ "42",
+ "1001"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "42 1001"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 embbeded format to verify that [[SMW::OFF]]/[[SMW:ON]] remain after transclusion",
+ "subject": "Example/P0449/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ASK"
+ ],
+ "propertyValues": []
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_STRICT",
+ "SMW_PARSER_INL_ERROR",
+ "SMW_PARSER_HID_CATS",
+ "SMW_PARSER_LINV"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0450.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0450.json
new file mode 100644
index 00000000..3c334e82
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0450.json
@@ -0,0 +1,94 @@
+{
+ "description": "Test in-text annotation with invisible chars (`wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0450/1",
+ "contents": "[[Left-To-Right ‎‎Mark::C++‎]] [[Left-To-Right Mark::C++]]"
+ },
+ {
+ "page": "Example/P0450/2",
+ "contents": "[[Right-To-Left â€Mark::ב×מת! -]] [[Right-To-Left Mark::ב×מת!†-]]"
+ },
+ {
+ "page": "Example/P0450/3",
+ "contents": "[[Has text::no shyness]] [[Has text::visible shy&shy;ness]] [[Has text::invisible shy­ness]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 Left-To-Right Mark chars",
+ "subject": "Example/P0450/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Left-To-Right Mark"
+ ],
+ "propertyValues": [
+ "C++"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 Right-To-Left Mark chars",
+ "subject": "Example/P0450/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Right-To-Left Mark"
+ ],
+ "propertyValues": [
+ "ב×מת! -"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 shy char",
+ "subject": "Example/P0450/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has text"
+ ],
+ "propertyValues": [
+ "no shyness",
+ "visible shyness",
+ "invisible shyness"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0451.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0451.json
new file mode 100644
index 00000000..8720ee3f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0451.json
@@ -0,0 +1,105 @@
+{
+ "description": "Test in-text `_dat` datatype, time zone, and JD output (#2454, `wgContLang=en`, `wgLang=en`, `smwgDVFeatures=SMW_DV_TIMEV_CM`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0451/1",
+ "contents": "{{#set:Has date=April 25, 2017 20:00-4:00}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/2",
+ "contents": "{{#set:Has date=April 25, 2017 20:00 EDT}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/3",
+ "contents": "{{#set:Has date=April 25, 2017 20:00-5:00}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/4",
+ "contents": "{{#set:Has date=April 25, 2017 21:00 EDT}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/5",
+ "contents": "{{#set:Has date=April 25, 2017 20:00-3:00}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/6",
+ "contents": "{{#set:Has date=April 25, 2017 19:00 EDT}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/7",
+ "contents": "{{#set:Has date=April 25, 2017 17:00-7:00}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/8",
+ "contents": "{{#set:Has date=April 25, 2017 14:00-10:00}} [[Category:P0451]]"
+ },
+ {
+ "page": "Example/P0451/Q.1",
+ "contents": "{{#ask: [[Category:P0451]] |?Has date |?Has date#LOCL#TZ |?Has date#JD=JD |format=list }}"
+ },
+ {
+ "page": "Example/P0451/9",
+ "contents": "[[Has date::2458119.500000]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 standard, TZ, and JD output",
+ "subject": "Example/P0451/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0451/1.*26 April 2017 00:00:00.*00:00:00 UTC, 26 April 2017.*2457869.5",
+ "Example/P0451/2.*26 April 2017 00:00:00.*20:00:00 EDT, 25 April 2017.*2457869.5",
+ "Example/P0451/3.*26 April 2017 01:00:00.*01:00:00 UTC, 26 April 2017.*2457869.5416667",
+ "Example/P0451/4.*26 April 2017 01:00:00.*21:00:00 EDT, 25 April 2017.*2457869.5416667",
+ "Example/P0451/5.*25 April 2017 23:00:00.*23:00:00 UTC, 25 April 2017.*2457869.4583333",
+ "Example/P0451/6.*25 April 2017 23:00:00.*19:00:00 EDT, 25 April 2017.*2457869.4583333",
+ "Example/P0451/7.*26 April 2017 00:00:00.*00:00:00 UTC, 26 April 2017.*2457869.5",
+ "Example/P0451/8.*26 April 2017 00:00:00.*00:00:00 UTC, 26 April 2017.*2457869.5"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (recognized as JD not as timestamp)",
+ "subject": "Example/P0451/9",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has date"
+ ],
+ "propertyValues": [
+ "2018-01-01T00:00:00"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "2458119.500000"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDVFeatures": [
+ "SMW_DV_TIMEV_CM"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0452.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0452.json
new file mode 100644
index 00000000..19ff7390
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0452.json
@@ -0,0 +1,71 @@
+{
+ "description": "Test in-text `_txt` datatype in combination with an \"Allows value\" output (#2342, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "page": "Has text",
+ "namespace":"SMW_NS_PROPERTY",
+ "contents": "[[Has type::Text]], [[Allows value::Doe]]"
+ },
+ {
+ "page": "Example/P0452/1",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has text::Doe]]"
+ },
+ {
+ "page": "Example/P0452/2",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has text::Do]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 test output of the valid [[Has text::Doe]] annotation",
+ "subject": "Example/P0452/1",
+ "assert-output": {
+ "to-contain": [
+ "Doe"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31-) test output of the invalid [[Has text::Do]] annotation",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0452/2",
+ "assert-output": {
+ "to-contain": [
+ "Do<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;Do&quot; is not in the list (Doe) of allowed values for the &quot;Has text&quot; property.\">"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31+) test output of the invalid [[Has text::Do]] annotation",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0452/2",
+ "assert-output": {
+ "to-contain": [
+ "Do<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;Do&quot; is not in the list (Doe) of allowed values for the &quot;Has text&quot; property.\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0453.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0453.json
new file mode 100644
index 00000000..05632c7a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0453.json
@@ -0,0 +1,41 @@
+{
+ "description": "Test in-text `_dat` annotation with `#LOCL#TO` (`wgLocalTZoffset`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P0453/1",
+ "contents": "[[Has date::1 Jan 1971 13:00]]"
+ },
+ {
+ "page": "Example/P0453/Q.1",
+ "contents": "{{#show: Example/P0453/1 |?Has date |?Has date#LOCL#TO }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0453/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_dat\" data-sort-value=\"2440953.0416667\">1 January 1971 13:00:00</td>",
+ "<td class=\"smwtype_dat\" data-sort-value=\"2440953.0416667\">15:00:00, 1 January 1971&#160;<sup title=\"ISO: 1971-01-01T13:00:00\">á´¸</sup></td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLocalTZoffset": 120
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0454.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0454.json
new file mode 100644
index 00000000..c1ed0946
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0454.json
@@ -0,0 +1,52 @@
+{
+ "description": "Test in-text annotation with enabled links in values on `&#91;`, `&#93;` (#2671, `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::text]]"
+ },
+ {
+ "page": "Example/P0454/1",
+ "contents": ""
+ },
+ {
+ "page": "Example/P0454/2",
+ "contents": "[[Example/P0454/1|&#91;&#91;Foo&#93;&#93;]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 `&#91;`/`&#93;` are kept during parsing",
+ "subject": "Example/P0454/2",
+ "assert-output": {
+ "to-contain": [
+ "<a href=.* title=\"Example/P0454/1\">&#91;&#91;Foo&#93;&#93;</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_STRICT",
+ "SMW_PARSER_INL_ERROR",
+ "SMW_PARSER_HID_CATS",
+ "SMW_PARSER_LINV"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0455.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0455.json
new file mode 100644
index 00000000..a829ba19
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0455.json
@@ -0,0 +1,244 @@
+{
+ "description": "Test paser/in-text annotation with unstripped tags (nowiki etc.) (`SMW_PARSER_UNSTRIP`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has description",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0455/1",
+ "contents": "[[Has description::<nowiki>Contains nowiki tag</nowiki>]]"
+ },
+ {
+ "page": "Example/P0455/2",
+ "contents": "[[Has description::<pre>Contains pre tag</pre>]]"
+ },
+ {
+ "page": "Example/P0455/3",
+ "contents": "[[Has description::<code><nowiki>{{#ask: [[Has strip::Markers]] }}</nowiki></code>]]"
+ },
+ {
+ "page": "Example/P0455/4",
+ "contents": "{{#set: Has description=<nowiki>Contains nowiki tag</nowiki> }}"
+ },
+ {
+ "page": "Example/P0455/5",
+ "contents": "{{#set: Has description=<pre>Contains pre tag</pre> }}"
+ },
+ {
+ "page": "Example/P0455/6",
+ "contents": "{{#set: Has description=<code><nowiki>{{#ask: [[Has strip::Markers]] }}</nowiki></code> }}"
+ },
+ {
+ "page": "Example/P0455/7",
+ "contents": "{{#subobject: Has description=<nowiki>Contains nowiki tag</nowiki> }}"
+ },
+ {
+ "page": "Example/P0455/8",
+ "contents": "{{#subobject: Has description=<pre>Contains pre tag</pre> }}"
+ },
+ {
+ "page": "Example/P0455/9",
+ "contents": "{{#subobject: Has description=<code><nowiki>{{#ask: [[Has strip::Markers]] }}</nowiki></code> }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 nowiki parse/unstrip",
+ "subject": "Example/P0455/1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_description",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;nowiki&gt;Contains nowiki tag&lt;/nowiki&gt;"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Contains nowiki tag"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 pre parse/unstrip",
+ "subject": "Example/P0455/2",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_description",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;pre&gt;Contains pre tag&lt;/pre&gt;"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<pre>Contains pre tag</pre>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 code/nowiki recursive parse/unstrip",
+ "subject": "Example/P0455/3",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_description",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;nowiki&gt;&lt;code&gt;&#x007B;&#x007B;#ask&#58; &#x005B;&#x005B;Has strip&#58;&#58;Markers]] }}&lt;/code&gt;&lt;/nowiki&gt;"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<code>{{#ask: [[Has strip::Markers]] }}</code>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 #set nowiki parse/unstrip",
+ "subject": "Example/P0455/4",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_description",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;nowiki&gt;Contains nowiki tag&lt;/nowiki&gt;"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 #set pre parse/unstrip",
+ "subject": "Example/P0455/5",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_description",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;pre&gt;Contains pre tag&lt;/pre&gt;"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 #set code/nowiki recursive parse/unstrip",
+ "subject": "Example/P0455/6",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "Has_description",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;nowiki&gt;&lt;code&gt;&#x007B;&#x007B;#ask&#58; &#x005B;&#x005B;Has strip&#58;&#58;Markers]] }}&lt;/code&gt;&lt;/nowiki&gt;"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 #subobject nowiki parse/unstrip",
+ "subject": "Example/P0455/7#_726a6109c10cb1ff73b7d5659ad54a18",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "Has_description",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;nowiki&gt;Contains nowiki tag&lt;/nowiki&gt;"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 #subobject pre parse/unstrip",
+ "subject": "Example/P0455/8#_74c67f7dc0f33736ec2d8f4f2132a585",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "Has_description",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;pre&gt;Contains pre tag&lt;/pre&gt;"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 #subobject code/nowiki recursive parse/unstrip",
+ "subject": "Example/P0455/9#_4bb289f3707ef1e08395efb545cae8f3",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 2,
+ "propertyKeys": [
+ "Has_description",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "&lt;nowiki&gt;&lt;code&gt;&#x007B;&#x007B;#ask&#58; &#x005B;&#x005B;Has strip&#58;&#58;Markers]] }}&lt;/code&gt;&lt;/nowiki&gt;"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_UNSTRIP",
+ "SMW_PARSER_STRICT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0456.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0456.json
new file mode 100644
index 00000000..568c8b38
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0456.json
@@ -0,0 +1,108 @@
+{
+ "description": "Test #subobject with assigned sortkey, default order etc.",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::text]]"
+ },
+ {
+ "page": "Example/P0456/1",
+ "contents": "{{#subobject: foo |Has text=foo }} {{#subobject: bar |Has text=bar }} {{#subobject: baz |Has text=baz }}"
+ },
+ {
+ "page": "Example/P0456/2",
+ "contents": "{{#subobject: baz |Has text=baz }} {{#subobject: foo |Has text=foo }} {{#subobject: bar |Has text=bar }}"
+ },
+ {
+ "page": "Example/P0456/Q.1",
+ "contents": "{{#ask: [[-Has subobject::Example/P0456/1]] |?Has text }}"
+ },
+ {
+ "page": "Example/P0456/Q.2",
+ "contents": "{{#ask: [[-Has subobject::Example/P0456/2]] |?Has text }}"
+ },
+ {
+ "page": "Example/P0456/3",
+ "contents": "{{#subobject: foo |Has text=foo }} {{#subobject: bar |Has text=bar |@sortkey=zzz }} {{#subobject: baz |Has text=baz }}"
+ },
+ {
+ "page": "Example/P0456/4",
+ "contents": "{{#subobject: baz |Has text=baz }} {{#subobject: foo |Has text=foo }} {{#subobject: bar |Has text=bar|@sortkey=zzz }}"
+ },
+ {
+ "page": "Example/P0456/Q.3",
+ "contents": "{{#ask: [[-Has subobject::Example/P0456/3]] |?Has text }}"
+ },
+ {
+ "page": "Example/P0456/Q.4",
+ "contents": "{{#ask: [[-Has subobject::Example/P0456/4]] |?Has text }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (default order without explicit sortkey)",
+ "subject": "Example/P0456/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" .*Example/P0456/1#bar\" title=\"Example/P0456/1\">Example/P0456/1#bar</a></span></td><td class=\"Has-text smwtype_txt\">bar</td></tr>",
+ "<tr data-row-number=\"2\" .*Example/P0456/1#baz\" title=\"Example/P0456/1\">Example/P0456/1#baz</a></span></td><td class=\"Has-text smwtype_txt\">baz</td></tr>",
+ "<tr data-row-number=\"3\" .*Example/P0456/1#foo\" title=\"Example/P0456/1\">Example/P0456/1#foo</a></span></td><td class=\"Has-text smwtype_txt\">foo</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 same as #0 (default order without explicit sortkey, order independent from the page position)",
+ "subject": "Example/P0456/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" .*Example/P0456/2#bar\" title=\"Example/P0456/2\">Example/P0456/2#bar</a></span></td><td class=\"Has-text smwtype_txt\">bar</td></tr>",
+ "<tr data-row-number=\"2\" .*Example/P0456/2#baz\" title=\"Example/P0456/2\">Example/P0456/2#baz</a></span></td><td class=\"Has-text smwtype_txt\">baz</td></tr>",
+ "<tr data-row-number=\"3\" .*Example/P0456/2#foo\" title=\"Example/P0456/2\">Example/P0456/2#foo</a></span></td><td class=\"Has-text smwtype_txt\">foo</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (with explicit sortkey)",
+ "subject": "Example/P0456/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" .*Example/P0456/3#baz\" title=\"Example/P0456/3\">Example/P0456/3#baz</a></span></td><td class=\"Has-text smwtype_txt\">baz</td></tr>",
+ "<tr data-row-number=\"2\" .*Example/P0456/3#foo\" title=\"Example/P0456/3\">Example/P0456/3#foo</a></span></td><td class=\"Has-text smwtype_txt\">foo</td></tr>",
+ "<tr data-row-number=\"3\" .*Example/P0456/3#bar\" title=\"Example/P0456/3\">Example/P0456/3#bar</a></span></td><td class=\"Has-text smwtype_txt\">bar</td></tr>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 same as #2 (with explicit sortkey, order independent from the page position)",
+ "subject": "Example/P0456/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" .*Example/P0456/4#baz\" title=\"Example/P0456/4\">Example/P0456/4#baz</a></span></td><td class=\"Has-text smwtype_txt\">baz</td></tr>",
+ "<tr data-row-number=\"2\" .*Example/P0456/4#foo\" title=\"Example/P0456/4\">Example/P0456/4#foo</a></span></td><td class=\"Has-text smwtype_txt\">foo</td></tr>",
+ "<tr data-row-number=\"3\" .*Example/P0456/4#bar\" title=\"Example/P0456/4\">Example/P0456/4#bar</a></span></td><td class=\"Has-text smwtype_txt\">bar</td></tr>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0457.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0457.json
new file mode 100644
index 00000000..be987d7f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0457.json
@@ -0,0 +1,70 @@
+{
+ "description": "Test named subobject caption display (#2895)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::text]]"
+ },
+ {
+ "page": "Example/P0457/1",
+ "contents": "{{#subobject:Foo bar|Has text=123|@category=P0457/1}}"
+ },
+ {
+ "page": "Example/P0457/2",
+ "contents": "{{#subobject:Foo bar|Has text=123|@category=P0457/2|display title of=Bar foo}}"
+ },
+ {
+ "page": "Example/P0457/Q.1",
+ "contents": "{{#ask: [[Category:P0457/1]] }}"
+ },
+ {
+ "page": "Example/P0457/Q.2",
+ "contents": "{{#ask: [[Category:P0457/2]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (named sobj without `_` in caption)",
+ "subject": "Example/P0457/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<a href=.*Example/P0457/1#Foo_bar\" title=\"Example/P0457/1\">Example/P0457/1#Foo bar</a>"
+ ],
+ "not-contain": [
+ "<a href=.*Example/P0457/1#Foo_bar\" title=\"Example/P0457/1\">Example/P0457/1#Foo_bar</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (named sobj without `_` in caption and `display title of`)",
+ "subject": "Example/P0457/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<a href=.*Example/P0457/2#Foo_bar\" title=\"Example/P0457/2\">Bar foo#Foo bar</a>"
+ ],
+ "not-contain": [
+ "<a href=.*Example/P0457/2#Foo_bar\" title=\"Example/P0457/2\">Example/P0457/2#Foo_bar</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0458.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0458.json
new file mode 100644
index 00000000..3ac5e7e2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0458.json
@@ -0,0 +1,72 @@
+{
+ "description": "Test keyword type `_keyw`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has keyword",
+ "contents": "[[Has type::Keyword]]"
+ },
+ {
+ "page": "Example/P0458/1",
+ "contents": "[[Has keyword::aBcDEF]]"
+ },
+ {
+ "page": "Example/P0458/2",
+ "contents": "[[Has keyword::abcdef]]"
+ },
+ {
+ "page": "Example/P0458/3",
+ "contents": "[[Has keyword::ABCDEF]]"
+ },
+ {
+ "page": "Example/P0458/Q.1",
+ "contents": "{{#ask: [[Has keyword::ABCDEF]] |?Has keyword }}"
+ },
+ {
+ "page": "Example/P0458/Q.2",
+ "contents": "{{#ask: [[Has keyword::abcdef]] |?Has keyword }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0458/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0458/1\" title=\"Example/P0458/1\">Example/P0458/1</a></td><td class=\"Has-keyword smwtype_keyw\">aBcDEF</td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0458/2\" title=\"Example/P0458/2\">Example/P0458/2</a></td><td class=\"Has-keyword smwtype_keyw\">abcdef</td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0458/3\" title=\"Example/P0458/3\">Example/P0458/3</a></td><td class=\"Has-keyword smwtype_keyw\">ABCDEF</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0458/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0458/1\" title=\"Example/P0458/1\">Example/P0458/1</a></td><td class=\"Has-keyword smwtype_keyw\">aBcDEF</td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0458/2\" title=\"Example/P0458/2\">Example/P0458/2</a></td><td class=\"Has-keyword smwtype_keyw\">abcdef</td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0458/3\" title=\"Example/P0458/3\">Example/P0458/3</a></td><td class=\"Has-keyword smwtype_keyw\">ABCDEF</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0459.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0459.json
new file mode 100644
index 00000000..7693ec54
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0459.json
@@ -0,0 +1,119 @@
+{
+ "description": "Test keyword type `_keyw` with a formatter schema (`smwgCompactLinkSupport`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_SCHEMA",
+ "page": "Keyword link formatter schema",
+ "contents": {
+ "import-from": "/../Fixtures/p-0459-keyword-formatter-schema.json"
+ }
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has keyword",
+ "contents": "[[Has type::Keyword]] [[Formatter schema::Keyword link formatter schema]]"
+ },
+ {
+ "page": "Example/P0459/1",
+ "contents": "[[Has keyword::aBcDEF]]"
+ },
+ {
+ "page": "Example/P0459/2",
+ "contents": "[[Has keyword::abcdef]]"
+ },
+ {
+ "page": "Example/P0459/3",
+ "contents": "[[Has keyword::ABCDEF]]"
+ },
+ {
+ "page": "Example/P0459/Q.1",
+ "contents": "{{#ask: [[Has keyword::ABCDEF]] |?Has keyword }}"
+ },
+ {
+ "page": "Example/P0459/Q.2",
+ "contents": "{{#ask: [[Has keyword::abcdef]] |?Has keyword }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Keyword link formatter schema",
+ "namespace": "SMW_NS_SCHEMA",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 6,
+ "propertyKeys": [
+ "_MDAT",
+ "_SCHEMA_DEF",
+ "_SCHEMA_DESC",
+ "_SCHEMA_TAG",
+ "_SCHEMA_TYPE",
+ "_SKEY"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Has keyword",
+ "namespace": "SMW_NS_PROPERTY",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_FORMAT_SCHEMA",
+ "_SKEY",
+ "_MDAT",
+ "_TYPE"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0459/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0459/1\" title=\"Example/P0459/1\">Example/P0459/1</a></td><td class=\"Has-keyword smwtype_keyw\"><a href=.*Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YUJjREVGLTVELTVEL2Zvcm1hdD1saXN0\" title=\"Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YUJjREVGLTVELTVEL2Zvcm1hdD1saXN0\">aBcDEF</a></td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0459/2\" title=\"Example/P0459/2\">Example/P0459/2</a></td><td class=\"Has-keyword smwtype_keyw\"><a href=.*Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YWJjZGVmLTVELTVEL2Zvcm1hdD1saXN0\" title=\"Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YWJjZGVmLTVELTVEL2Zvcm1hdD1saXN0\">abcdef</a></td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0459/3\" title=\"Example/P0459/3\">Example/P0459/3</a></td><td class=\"Has-keyword smwtype_keyw\"><a href=.*Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6QUJDREVGLTVELTVEL2Zvcm1hdD1saXN0\" title=\"Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6QUJDREVGLTVELTVEL2Zvcm1hdD1saXN0\">ABCDEF</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0459/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0459/1\" title=\"Example/P0459/1\">Example/P0459/1</a></td><td class=\"Has-keyword smwtype_keyw\"><a href=.*Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YUJjREVGLTVELTVEL2Zvcm1hdD1saXN0\" title=\"Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YUJjREVGLTVELTVEL2Zvcm1hdD1saXN0\">aBcDEF</a></td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0459/2\" title=\"Example/P0459/2\">Example/P0459/2</a></td><td class=\"Has-keyword smwtype_keyw\"><a href=.*Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YWJjZGVmLTVELTVEL2Zvcm1hdD1saXN0\" title=\"Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6YWJjZGVmLTVELTVEL2Zvcm1hdD1saXN0\">abcdef</a></td>",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/P0459/3\" title=\"Example/P0459/3\">Example/P0459/3</a></td><td class=\"Has-keyword smwtype_keyw\"><a href=.*Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6QUJDREVGLTVELTVEL2Zvcm1hdD1saXN0\" title=\"Special:Ask/cl:LTVCLTVCSGFzLTIwa2V5d29yZDo6QUJDREVGLTVELTVEL2Zvcm1hdD1saXN0\">ABCDEF</a></td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgCompactLinkSupport": true,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "SMW_NS_SCHEMA": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0460.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0460.json
new file mode 100644
index 00000000..8e1dee32
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0460.json
@@ -0,0 +1,218 @@
+{
+ "description": "Test in-text `_num`, `_qty` in combination with an \"Allows value\" range, bounds",
+ "setup": [
+ {
+ "page": "Has ranged number",
+ "namespace":"SMW_NS_PROPERTY",
+ "contents": "[[Has type::Number]], [[Allows value::>1]] [[Allows value::<10]] [[Allows value::20]]"
+ },
+ {
+ "page": "Has bounded number",
+ "namespace":"SMW_NS_PROPERTY",
+ "contents": "[[Has type::Number]], [[Allows value::1..10]] [[Allows value::50...60]] [[Allows value::70]]"
+ },
+ {
+ "page": "Has bounded quantity",
+ "namespace":"SMW_NS_PROPERTY",
+ "contents": "[[Has type::Quantity]], [[Allows value::1..200]] [[Corresponds to::1 km²]] [[Corresponds to::0.38613 sq mi]] [[Corresponds to::1000 m²]]"
+ },
+ {
+ "page": "Example/P0460/1",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has ranged number::2]]"
+ },
+ {
+ "page": "Example/P0460/2",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has ranged number::20]]"
+ },
+ {
+ "page": "Example/P0460/3",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has ranged number::10]]"
+ },
+ {
+ "page": "Example/P0460/4",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has bounded number::1]]"
+ },
+ {
+ "page": "Example/P0460/5",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has bounded number::60]]"
+ },
+ {
+ "page": "Example/P0460/6",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has bounded number::70]]"
+ },
+ {
+ "page": "Example/P0460/7",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has bounded number::60.1]]"
+ },
+ {
+ "page": "Example/P0460/8",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has bounded quantity::200m²]]"
+ },
+ {
+ "page": "Example/P0460/9",
+ "namespace":"NS_MAIN",
+ "contents": "[[Has bounded quantity::200.1km²]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (number, inside the number range)",
+ "subject": "Example/P0460/1",
+ "assert-output": {
+ "to-contain": [
+ "2"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (number, outside of number range but matches discrete value)",
+ "subject": "Example/P0460/2",
+ "assert-output": {
+ "to-contain": [
+ "20"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31-) (number, invalid, outside of specified range)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0460/3",
+ "assert-output": {
+ "to-contain": [
+ "10<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;10&quot; is not in the list (&gt;1, ) of allowed values for the &quot;Has ranged number&quot; property.\">"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31+) (number, invalid, outside of specified range)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0460/3",
+ "assert-output": {
+ "to-contain": [
+ "10<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;10&quot; is not in the list (&gt;1, ) of allowed values for the &quot;Has ranged number&quot; property.\">"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (number, inside the bounds)",
+ "subject": "Example/P0460/4",
+ "assert-output": {
+ "to-contain": [
+ "1"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (number, inside the seconds bounds)",
+ "subject": "Example/P0460/5",
+ "assert-output": {
+ "to-contain": [
+ "60"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (number, outside the bounds but matches discrete value)",
+ "subject": "Example/P0460/6",
+ "assert-output": {
+ "to-contain": [
+ "70"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (1.31-) (number, invalid, outside of specified bounds)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0460/7",
+ "assert-output": {
+ "to-contain": [
+ "60.1<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;60.1&quot; is not in the list (1..10, 50...60, 70) of allowed values for the &quot;Has bounded number&quot; property.\">"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6 (1.31+) (number, invalid, outside of specified bounds)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0460/7",
+ "assert-output": {
+ "to-contain": [
+ "60.1<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;60.1&quot; is not in the list (1..10, 50...60, 70) of allowed values for the &quot;Has bounded number&quot; property.\">"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7 (quantity, inside the bounds)",
+ "subject": "Example/P0460/8",
+ "assert-output": {
+ "to-contain": [
+ "0.2 km²"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 (1.31-) (quantity, invalid, outside of specified range, bounds)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0460/9",
+ "assert-output": {
+ "to-contain": [
+ "200.1km²<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;200.1 km²&quot; is not within that range of &quot;1..200&quot; specified by the allows value constraint for the &quot;Has bounded quantity&quot; property.\">"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8 (1.31+) (quantity, invalid, outside of specified range, bounds)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0460/9",
+ "assert-output": {
+ "to-contain": [
+ "200.1km²<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\" data-title=\"Warning\" title=\"&quot;200.1 km²&quot; is not within that range of &quot;1..200&quot; specified by the allows value constraint for the &quot;Has bounded quantity&quot; property.\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0461.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0461.json
new file mode 100644
index 00000000..cf24f3be
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0461.json
@@ -0,0 +1,92 @@
+{
+ "description": "Test `_wpg` value with lower/upper first case letter +DISPLAYTITLE (#3587, `wgRestrictDisplayTitle`, `wgCapitalLinks`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "P0461/1",
+ "contents": "[[Has number::123]] [[Has text::abc]] [[Category:P0461]] {{DISPLAYTITLE:p0461/1}}"
+ },
+ {
+ "page": "P0461/2",
+ "contents": "[[Category:P0461]] [[Has text::ABC]] {{DISPLAYTITLE:p0461/2}}"
+ },
+ {
+ "page": "P0461/Q.1",
+ "contents": "{{#show: p0461/1 |?Has number |intro=p0461: }}"
+ },
+ {
+ "page": "P0461/Q.2",
+ "contents": "{{#show: P0461/1 |?Has number |intro=P0461: }}"
+ },
+ {
+ "page": "P0461/Q.3",
+ "contents": "{{#ask: [[p0461/1]] |?Has text |intro=p0461: |format=plain |mainlabel=- |headers=hide }}"
+ },
+ {
+ "page": "P0461/Q.4",
+ "contents": "{{#ask: [[P0461/1]] |?Has text |intro=P0461: |format=plain |mainlabel=- |headers=hide }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (#show, lower case `p0461`)",
+ "subject": "P0461/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "p0461:123"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (#show, upper case `P0461`)",
+ "subject": "P0461/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "P0461:123"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (#ask, lower case `p0461`)",
+ "subject": "P0461/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "p0461:abc"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (#ask, upper case `P0461`)",
+ "subject": "P0461/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "P0461:abc"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgCapitalLinks": true,
+ "wgRestrictDisplayTitle": false
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0501.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0501.json
new file mode 100644
index 00000000..6eb67ec8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0501.json
@@ -0,0 +1,35 @@
+{
+ "description": "Test `#concept` on predefined property (`wgContLang=en`, `wgLang=es`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Example/P0501/1",
+ "contents": "{{#concept: [[Modification date::+]] |Modification date}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 canonical representation, not userlang specific",
+ "subject": "Example/P0501/1",
+ "namespace": "SMW_NS_CONCEPT",
+ "assert-output": {
+ "to-contain": [
+ "<p class=\"concept-documenation\">Modification date</p><pre>&#91;&#91;Modification date::+]]</pre>"
+ ],
+ "not-contain": [
+ "<p class=\"concept-documenation\">Modification date</p><pre>&#91;&#91;Fecha de modificación::+]]</pre>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "es"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0502.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0502.json
new file mode 100644
index 00000000..aecac40f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0502.json
@@ -0,0 +1,194 @@
+{
+ "description": "Test in-text annotation allows value list (#2295, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw allows list Publication categories",
+ "contents": {
+ "import-from": "/../Fixtures/p-0502.txt"
+ }
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw allows list error",
+ "contents": {
+ "import-from": "/../Fixtures/p-0502-error.txt"
+ }
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw allows list license",
+ "contents": "* BSD-2-Clause|2-clause BSD License (BSD-2-Clause)\n* Zlib|zlib/libpng license (Zlib)"
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw allows list other license.json",
+ "contents": {
+ "import-from": "/../Fixtures/p-0502-other-license.json"
+ }
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has list",
+ "contents": "[[Has type::Text]] [[Allows value list::Publication categories]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has combined list",
+ "contents": "[[Has type::Text]] [[Allows value list::Publication categories]] [[Allows value::abc]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has combined error list",
+ "contents": "[[Has type::Text]] [[Allows value list::error]] [[Allows value::Foo]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has license",
+ "contents": "[[Has type::Text]] [[Allows value list::license]] [[Allows value list::other license.json]]"
+ },
+ {
+ "page": "Example/P0502/1",
+ "contents": "[[Has list::abc]]"
+ },
+ {
+ "page": "Example/P0502/2",
+ "contents": "[[Has list::Document]] [[Has list::Manuscript]]"
+ },
+ {
+ "page": "Example/P0502/3",
+ "contents": "[[Has combined list::abc]] [[Has combined list::Manuscript]]"
+ },
+ {
+ "page": "Example/P0502/4",
+ "contents": "[[Has combined error list::Foobar]]"
+ },
+ {
+ "page": "Example/P0502/5",
+ "contents": "[[Has license::Zlib]]"
+ },
+ {
+ "page": "Example/P0502/6",
+ "contents": "[[Has license::PD]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 invalid assignment",
+ "subject": "Example/P0502/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 valid assignment",
+ "subject": "Example/P0502/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has list"
+ ],
+ "propertyValues": [
+ "Document",
+ "Manuscript"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 valid assignment",
+ "subject": "Example/P0502/3",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has combined list"
+ ],
+ "propertyValues": [
+ "abc",
+ "Manuscript"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 error output",
+ "subject": "Example/P0502/4",
+ "assert-output": {
+ "to-contain": [
+ "\"Foobar\" is not in the list (Foo, Bar)"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 assignment on key (* key|value)",
+ "subject": "Example/P0502/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has license"
+ ],
+ "propertyValues": [
+ "Zlib"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 assignment from JSON",
+ "subject": "Example/P0502/6",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has license"
+ ],
+ "propertyValues": [
+ "PD"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0503.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0503.json
new file mode 100644
index 00000000..9a908ac9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0503.json
@@ -0,0 +1,106 @@
+{
+ "description": "Test in-text annotation `_uri` on valid/invalid scheme/path",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/P0503/1",
+ "contents": "[[Has url::ftp://example.com/foo]]"
+ },
+ {
+ "page": "Example/P0503/2",
+ "contents": "[[Has url::User:Test]]"
+ },
+ {
+ "page": "Example/P0503/3",
+ "contents": "[[Has url::http:///]]"
+ },
+ {
+ "page": "Example/P0503/Q.1",
+ "contents": "{{#ask: [[Has url::User:Test]] |default=No result }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 valid ftp",
+ "subject": "Example/P0503/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has url"
+ ],
+ "propertyValues": [
+ "ftp://example.com/foo"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 invalid User:",
+ "subject": "Example/P0503/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (allow invalid scheme in query context)",
+ "subject": "Example/P0503/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "No result"
+ ],
+ "not-contain": [
+ "<span class=\"smw-highlighter\" data-type=\"4\" data-state=\"inline\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 invalid path `///`",
+ "subject": "Example/P0503/3#_ERRd3ce18ed907900b1ec8f6a2b7bce6aea",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_ERRT",
+ "_ERRP"
+ ],
+ "propertyValues": [
+ "\"http:///\" has been idendified to contain an invalid \"/\" authority or path component."
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0504.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0504.json
new file mode 100644
index 00000000..a80aa705
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0504.json
@@ -0,0 +1,49 @@
+{
+ "description": "Test Equivalent URI (`__spu`)",
+ "setup": [
+ {
+ "namespace": "NS_MAIN",
+ "page": "Test:P0504/1",
+ "contents": "[[Equivalent URI::http://www.wikidata.org/entity/Q20728]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#3601, Equivalent URI property must not be declarative, (i. e., it can be used on subject pages, as well as property and category pages)",
+ "subject": "Test:P0504/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_URI",
+ "_MDAT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "http://www.wikidata.org/entity/Q20728"
+ ]
+ }
+ },
+ "assert-output": {
+ "not-contain": [
+ "is a declarative property"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0701.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0701.json
new file mode 100644
index 00000000..58bfddfc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0701.json
@@ -0,0 +1,76 @@
+{
+ "description": "Test to create inverted annotation using a #ask/template combination (#711, `import-annotation=true`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Located in",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Location of",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Location",
+ "contents": "<includeonly>[[Located in::{{{Located in}}}]]</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "InvertPropertySetter",
+ "contents": "<includeonly>{{#set:|{{{#userparam}}}={{{1}}} }}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "InvertPropertyDeclarator",
+ "contents": "<includeonly>{{#ask:[[{{{1}}}::{{PAGENAME}}]]|link=none|sep=|template=InvertPropertySetter|userparam={{{2}}}|format=template|import-annotation=true}}</includeonly>"
+ },
+ {
+ "page": "Belgium",
+ "contents": "{{Location|Located in=Europe}}"
+ },
+ {
+ "page": "Italy",
+ "contents": "{{Location|Located in=Europe}}"
+ },
+ {
+ "page": "Europe",
+ "contents": "{{InvertPropertyDeclarator|Located in|Location of}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 inverse annotation",
+ "subject": "Europe",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Location_of",
+ "_ASK"
+ ],
+ "propertyValues": [
+ "Italy",
+ "Belgium"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgCapitalLinks": true,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0702.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0702.json
new file mode 100644
index 00000000..899c34c3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0702.json
@@ -0,0 +1,99 @@
+{
+ "description": "Test #ask with `format=table` on inverse property/printrequest (#1270, #1360)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has inverse prop",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has query",
+ "contents": "(Remove set display title from p-0438)"
+ },
+ {
+ "page": "Example/P0702/1",
+ "contents": "{{#subobject:|Has inverse prop=InverseExample|Has number=4040}}"
+ },
+ {
+ "page": "Example/P0702/1/1",
+ "contents": "{{#ask: [[-Has inverse prop::<q>[[-Has subobject::Example/P0702/1]]</q>]]|?-Has inverse prop||?-Has inverse prop=LabelOnInversePrintout|format=table}}"
+ },
+ {
+ "page": "Example/P0702/2",
+ "contents": "[[-Has inverse prop::Invalid in-text annotation]]"
+ },
+ {
+ "page": "Example/P0702/3/1",
+ "contents": "{{#ask: [[-Has query::Example/P0702/1/1]]|?-Has query |format=table}}"
+ },
+ {
+ "page": "Example/P0702/3/2",
+ "contents": "{{#ask: [[-Has query::Example/P0702/1/1]]|?-Has query=AnotherLabel |format=table}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 table output using inverse property (label is inverse, link is to normal property)",
+ "subject": "Example/P0702/1/1",
+ "assert-output": {
+ "to-contain": [
+ "Property:Has_inverse_prop\" title=\"Property:Has inverse prop\">-Has inverse prop</a>",
+ ">InverseExample</a>",
+ "title=\"Example/P0702/1\">Example/P0702/1</a>",
+ ">LabelOnInversePrintout</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 in-text inverse annotation",
+ "subject": "Example/P0702/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ],
+ "propertyValues": []
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (inverse indicator on predefined property)",
+ "subject": "Example/P0702/3/1",
+ "assert-output": {
+ "to-contain": [
+ "<a href=.*Property:Has_query\" title=\"Property:Has query\">-Has query</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (custom label overrides any inverse indicator from property)",
+ "subject": "Example/P0702/3/2",
+ "assert-output": {
+ "to-contain": [
+ "<a href=.*Property:Has_query\" title=\"Property:Has query\">AnotherLabel</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0703.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0703.json
new file mode 100644
index 00000000..f1f3371d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0703.json
@@ -0,0 +1,64 @@
+{
+ "description": "Test `#ask` on `format=table` using different printrequest label output (#1270, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0703/1",
+ "contents": "[[Has text::P0703]]"
+ },
+ {
+ "page": "Example/P0703/2",
+ "contents": "[[Has text::P0703]]"
+ },
+ {
+ "page": "Example/P0703/Q.1",
+ "contents": "{{#ask: [[Has text::P0703]] |?Has text=<span style=\"color: green; font-size: 120%;\">Label</span> |format=table |limit=1 }}"
+ },
+ {
+ "page": "Example/P0703/Q.2",
+ "contents": "{{#ask: [[Has text::P0703]] |?Has text=Label {{#info:Text info.}} |format=table |limit=1 }}",
+ "message-cache": "clear"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0703/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:Has text\"><span style=\"color: green; font-size: 120%;\">Label</span>",
+ "Special:Ask/-5B-5BHas-20text::P0703-5D-5D/-3FHas-20text=-3Cspan-20style=&quot;color:-20green-3B-20font-2Dsize:-20120-25-3B&quot;-3ELabel-3C-2Fspan-3E/mainlabel=/limit=1/offset=1/format=table"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 with #info parser",
+ "subject": "Example/P0703/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:Has text\">Label <span class=\"smw-highlighter\" data-type=\"6\" data-state=\"persistent\" data-title=\"Information\" title=\"Text info.\">",
+ "<span class=\"smwtticon info\"></span><span class=\"smwttcontent\">Text info.</span></span>",
+ "Special:Ask/-5B-5BHas-20text::P0703-5D-5D/-3FHas-20text=Label-20-3Cspan-20class=&quot;smw-2Dhighlighter&quot;-20data-2Dtype=&quot;6&quot;-20data-2Dstate=&quot;persistent&quot;-20data-2Dtitle=&quot;Information&quot;-20title=&quot;Text-20info.&quot;-3E-3Cspan-20class=&quot;smwtticon-20info&quot;-3E-3C-2Fspan-3E-3Cspan-20class=&quot;smwttcontent&quot;-3EText-20info.-3C-2Fspan-3E-3C-2Fspan-3E/mainlabel=/limit=1/offset=1/format=table"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0704.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0704.json
new file mode 100644
index 00000000..c1a3d87d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0704.json
@@ -0,0 +1,56 @@
+{
+ "description": "Test `#ask` sanitization of printrequest labels to avoid XSS injection (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0704/1",
+ "contents": "[[Has text::P0704]]"
+ },
+ {
+ "page": "Example/P0704/Q.1",
+ "contents": "{{#ask: [[Has text::P0704]] |?Has text=Some <div onmouseover=\"alert('<?php echo htmlspecialchars($xss) ?>')\"> |format=table |limit=1 }}"
+ },
+ {
+ "page": "Example/P0704/Q.2",
+ "contents": "{{#ask: [[Has text::P0704]] |?Has text=Some <a href=\"javascript:alert('<?php echo htmlspecialchars($xss) ?>')\"> |format=table |limit=1 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (avoid XSS through sanitization)",
+ "subject": "Example/P0704/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:Has text\">Some &lt;div onmouseover=\"alert('&lt;?php echo htmlspecialchars($xss) ?&gt;')\"&gt;"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (avoid XSS through sanitization)",
+ "subject": "Example/P0704/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:Has text\">Some &lt;a href=\"javascript:alert('&lt;?php echo htmlspecialchars($xss) ?&gt;')\"&gt;"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0705.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0705.json
new file mode 100644
index 00000000..6d678b64
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0705.json
@@ -0,0 +1,98 @@
+{
+ "description": "Test `#ask`/ NS_FILE option (`wgContLang=en`, `wgLang=en`, `wgEnableUploads`, `wgFileExtensions`, 'wgDefaultUserOptions')",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_FILE",
+ "page": "P0705.png",
+ "contents": {
+ "upload": {
+ "file" : "/../Fixtures/image-upload-480.png",
+ "text" : "[[Has file::{{FULLPAGENAME}}]] [[Has caption::123]] {{#subobject:Test|Has text=Foo}}"
+ }
+ }
+ },
+ {
+ "page": "Example/P0705/Q.1",
+ "contents": "{{#ask: [[Has file::+]] |?Has file |format=table |limit=1 }}"
+ },
+ {
+ "page": "Example/P0705/Q.2",
+ "contents": "{{#ask: [[Has file::+]] |?Has file#120px;thumb;<b>{{#show: File:P0705.png |?Has caption |link=none}}</b>[[Extra]] |format=table |limit=1 }}"
+ },
+ {
+ "page": "Example/P0705/Q.3",
+ "contents": "{{#ask: [[File:+]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0705/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "class=\"image\"><img alt=\"P0705.png\"",
+ "300px-P0705.png\" width=\"300\" height=\"300\" style=\"vertical-align: text-top\" class=\"thumbborder\""
+ ],
+ "not-contain": [
+ "P0705.png\" width=\"480\" height=\"480\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 with options",
+ "subject": "Example/P0705/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "300px-P0705.png\" width=\"300\" height=\"300\" style=\"vertical-align: text-top\" class=\"thumbborder\"",
+ "class=\"image\"><img alt=\"P0705.png\"",
+ "120px-P0705.png\" width=\"120\" height=\"120\" class=\"thumbimage\"",
+ "<b>123</b>",
+ "class=\"thumb tright\"",
+ "<div class=\"thumbcaption\"><div class=\"magnify\">",
+ "Extra"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (subobject is displayed as normal link and not with an image reference)",
+ "subject": "Example/P0705/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smw-subobject-entity\"><a href=.*P0705.png#Test\" title=.*P0705.png\">P0705.png#Test</a></span>",
+ "<a href=.*P0705.png\" class=\"image\"><img alt=\"P0705.png\" .*class=\"thumbborder\" .*</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgEnableUploads": true,
+ "wgFileExtensions": [
+ "png"
+ ],
+ "wgDefaultUserOptions": {
+ "thumbsize": 5
+ },
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_FILE": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0706.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0706.json
new file mode 100644
index 00000000..e2bf0f07
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0706.json
@@ -0,0 +1,183 @@
+{
+ "description": "Test `#ask` on `format=template` with message parse (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "page": "Example/P0706/1",
+ "contents": "[[P0706::P0706]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/Tmpl0706",
+ "contents": "{{{1}}}"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/Tmpl0706withAnnotationDeep",
+ "contents": "<includeonly>[[Tmpl0706withAnnotationDeep::789]]</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/Tmpl0706withAnnotation",
+ "contents": "<includeonly>{{#set:|Tmpl0706withAnnotation=123}} [[Tmpl0706withAnnotation::456]] {{Example/Tmpl0706withAnnotationDeep}}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/Tmpl0706ResultOutput",
+ "contents": "<includeonly>{{{1}}} {{Example/Tmpl0706withAnnotation}}</includeonly>"
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Test/Msg0706/1",
+ "contents": "{{#ask: [[P0706::P0706]] |?P0706 |link=none |template=Example/Tmpl0706 |format=template }}"
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Test/Msg0706/2",
+ "contents": "{{#ask: [[P0706::P0706]] |?P0706 |link=none |template=Example/Tmpl0706 |format=template }}"
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Test/Msg0706/3",
+ "contents": "{{#ask: [[P0706::P0706]] |?P0706 |link=none |template=Example/Tmpl0706 |format=list }}"
+ },
+ {
+ "page": "Test/P0706/4",
+ "contents": "{{#ask: [[P0706::P0706]] |?P0706 |link=none |template=Example/Tmpl0706ResultOutput |format=template }}"
+ },
+ {
+ "page": "Test/P0706/5",
+ "contents": "{{#ask: [[P0706::P0706]] |?P0706 |link=none |template=Example/Tmpl0706ResultOutput |format=template |import-annotation=true }}"
+ },
+ {
+ "page": "Test/P0706/6",
+ "contents": "{{#ask: [[P0706::P0706]] |?P0706 |link=none |template=Example/Tmpl0706ResultOutput |format=template }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 template format, msg parse outputs [[SMW::off]]/[[SMW::on]]",
+ "subject": "Test/Msg0706/1",
+ "assert-msgoutput": {
+ "to-contain": [
+ "Example/P0706/1"
+ ],
+ "not-contain": [
+ ">SMW::off</a>",
+ ">SMW::on</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 template format, msg parse to avoid [[SMW::off]]/[[SMW::on]]",
+ "subject": "Test/Msg0706/2",
+ "assert-msgoutput": {
+ "to-contain": [
+ "Example/P0706/1"
+ ],
+ "not-contain": [
+ ">SMW::off</a>",
+ ">SMW::on</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 list format, msg parse to avoid [[SMW::off]]/[[SMW::on]]",
+ "subject": "Test/Msg0706/3",
+ "assert-msgoutput": {
+ "to-contain": [
+ "Example/P0706/1"
+ ],
+ "not-contain": [
+ ">SMW::off</a>",
+ ">SMW::on</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (no foreign annotation import)",
+ "subject": "Test/P0706/4",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/P0706/1",
+ "456",
+ "789"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (import foreign annotation)",
+ "subject": "Test/P0706/5",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY",
+ "Tmpl0706withAnnotation",
+ "Tmpl0706withAnnotationDeep"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/P0706/1",
+ "456",
+ "789"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (no foreign annotation import)",
+ "subject": "Test/P0706/6",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ASK",
+ "_MDAT",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/P0706/1",
+ "456",
+ "789"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0707.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0707.json
new file mode 100644
index 00000000..29f4501d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0707.json
@@ -0,0 +1,45 @@
+{
+ "description": "Test `#ask` with enabled execution limit (`wgContLang=en`, `wgLang=en`, `smwgQExpensiveThreshold`, `smwgQExpensiveExecutionLimit`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0707/1",
+ "contents": "[[Has text::123]]"
+ },
+ {
+ "page": "Example/P0707/Q.1",
+ "contents": "{{#ask: [[Has text::+]] |?Has text }} {{#ask: [[Has text::123]] |?Has text }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0707/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/P0707/1\">Example/P0707/1",
+ "title=\"The parser function has reached the limit for expensive executions"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQExpensiveExecutionLimit": 1,
+ "smwgQExpensiveThreshold": 0,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0708.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0708.json
new file mode 100644
index 00000000..46858e90
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0708.json
@@ -0,0 +1,61 @@
+{
+ "description": "Test `#ask` NS_FILE and DISPLAYTITLE (`wgContLang=en`, `wgLang=en`, `wgEnableUploads`, `wgFileExtensions`, 'wgDefaultUserOptions', `wgRestrictDisplayTitle`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_FILE",
+ "page": "P0708-text-file.txt",
+ "contents": {
+ "upload": {
+ "file" : "/../Fixtures/file-upload.txt",
+ "text" : "[[File type::txt]] {{DISPLAYTITLE:DIFFERENT TITLE}}"
+ }
+ }
+ },
+ {
+ "page": "Example/P0708/Q.1",
+ "contents": "{{#ask: [[File type::txt]] |format=table |limit=1 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (using DISPLAYTITLE)",
+ "subject": "Example/P0708/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<a href=\".*:P0708-text-file.txt\" title=\"File:P0708-text-file.txt\">DIFFERENT TITLE</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgRestrictDisplayTitle": false,
+ "wgEnableUploads": true,
+ "wgFileExtensions": [
+ "png",
+ "txt"
+ ],
+ "wgDefaultUserOptions": {
+ "thumbsize": 5
+ },
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_FILE": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0709.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0709.json
new file mode 100644
index 00000000..9f1d5e1b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0709.json
@@ -0,0 +1,104 @@
+{
+ "description": "Test #ask with `format=table` on inverse property, property path",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "P0709/1",
+ "contents": "[[Has number::123]] [[Has page::ABC]] [[Category:P0709]]"
+ },
+ {
+ "page": "P0709/2",
+ "contents": "[[Has number::1234]] [[Has page::DEF]] [[Category:P0709]]"
+ },
+ {
+ "page": "P0709/3",
+ "contents": "{{#subobject:A |@category=P0709}} {{#subobject:B |@category=P0709}}"
+ },
+ {
+ "page": "P0709/Q.1",
+ "contents": "{{#ask: [[-Has page.Has number::123]] |?Has page |format=table}}"
+ },
+ {
+ "page": "P0709/Q.2",
+ "contents": "{{#ask: [[-Has page.Has number::+]] |?Has page |order=asc |format=table}}"
+ },
+ {
+ "page": "P0709/Q.3",
+ "contents": "{{#ask: [[-Has page.Has number::+]] |?Has page |order=desc |format=table}}"
+ },
+ {
+ "page": "P0709/Q.4",
+ "contents": "{{#ask: [[-Has subobject::+]] [[Category:P0709]] |order=asc |format=table}}"
+ },
+ {
+ "page": "P0709/Q.5",
+ "contents": "{{#ask: [[-Has number::+]] |format=table |default=is empty}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (-Has page.Has number::123)",
+ "subject": "P0709/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=\".*\">ABC</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (-Has page.Has number::+, sort=asc)",
+ "subject": "P0709/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=\".*\">ABC</a></td>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=\".*\">DEF</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (-Has page.Has number::+, sort=desc)",
+ "subject": "P0709/Q.3",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=\".*\">DEF</a></td>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=\".*\">ABC</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (-Has subobject::+, sort=asc)",
+ "subject": "P0709/Q.4",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><span class=\"smw-subobject-entity\"><a href=\".*\">P0709/3#A</a></span></td></tr>",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><span class=\"smw-subobject-entity\"><a href=\".*\">P0709/3#B</a></span></td></tr>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0710.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0710.json
new file mode 100644
index 00000000..32af1799
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0710.json
@@ -0,0 +1,66 @@
+{
+ "description": "Test `#ask` with `[[Category::Foo]]`",
+ "setup": [
+ {
+ "page": "P0710/0",
+ "namespace":"NS_MAIN",
+ "contents": "{{#ask: [[Category::Foo]] }}"
+ },
+ {
+ "page": "P0710/1",
+ "namespace":"NS_MAIN",
+ "contents": "{{#ask: [[Category::Foo||Bar]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "P0710/0",
+ "assert-output": {
+ "to-contain": [
+ "\"[[Category&#58;&#58;Foo]]\" is not recognized as valid category or value annotation."
+ ]
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_ERRC",
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ],
+ "propertyValues": [
+ "P0710/0#0##_ERRc4925219842fff8c0078c42d61051c5e",
+ "P0710/0#0##_ERR32617756f0f702a55404d89059af32b8"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (with disjunction)",
+ "subject": "P0710/1",
+ "assert-output": {
+ "to-contain": [
+ "\"[[Category&#58;&#58;Foo||Bar]]\" is not recognized as valid category or value annotation."
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0711.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0711.json
new file mode 100644
index 00000000..52c3e57f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0711.json
@@ -0,0 +1,149 @@
+{
+ "description": "Test `#ask` with `||` condition (#3473)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "P0711/0",
+ "contents": "[[Has number::123]] [[Has page::ABC]] [[Category:P0711/0]]"
+ },
+ {
+ "page": "P0711/1",
+ "contents": "[[Has number::1234]] [[Has page::DEF]] [[Category:P0711/1]]"
+ },
+ {
+ "page": "P0711/Q.1",
+ "contents": "{{#ask: [[Category:P0711/0]] || [[Category:P0711/1]] }}"
+ },
+ {
+ "page": "P0711/Q.2",
+ "contents": "{{#ask: [[Category:P0711/0]][[Has number::1234]] || [[Category:P0711/1]] |format=table |limt=1 }}"
+ },
+ {
+ "page": "P0711/Q.3",
+ "contents": "{{#ask: [[Category:P0711/0||P0711/1]] [[Has number::1234]] || [[Category:P0711/1]] |format=table |limt=1 }}"
+ },
+ {
+ "page": "P0711/Q.4",
+ "contents": "{{#ask: [[Category:P0711/0]] || [[Has number::1234]] || [[Category:P0711/1]] |format=table |limt=1 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 ([[Category:P0711/0]] || [[Category:P0711/1]])",
+ "subject": "P0711/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "P0711/0",
+ "P0711/1"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 ([[Category:P0711/0]] || [[Category:P0711/1]] )",
+ "subject": "P0711/Q.1#_QUERY242ebc6ec4e4f26fdf094cbe459c5a7c",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKDE",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKST",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[[Category:P0711/0||P0711/1]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 ( [[Category:P0711/0]][[Has number::1234]] || [[Category:P0711/1]] )",
+ "subject": "P0711/Q.2#_QUERY4d17e3c435adb842705d03a0ce6e80da",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKDE",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKST",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "<q>[[Category:P0711/0]] [[Has number::1234]] OR [[Category:P0711/1]]</q>"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 ( [[Category:P0711/0||P0711/1]][[Has number::1234]] || [[Category:P0711/1]] )",
+ "subject": "P0711/Q.3#_QUERY5eb422bd01f40410eaa3586b5134eb32",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKDE",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKST",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "<q>[[Category:P0711/0||P0711/1]] [[Has number::1234]] OR [[Category:P0711/1]]</q>"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 ( [[Category:P0711/0]] || [[Has number::1234]] || [[Category:P0711/1]] )",
+ "subject": "P0711/Q.4#_QUERYfcb13e9c99c91f99011555adf4327898",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKDE",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKST",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "<q>[[Category:P0711/0||P0711/1]] OR <q>[[Has number::1234]]</q> </q>"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
+
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0712.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0712.json
new file mode 100644
index 00000000..0a9c2811
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0712.json
@@ -0,0 +1,64 @@
+{
+ "description": "Test `#ask` on `format=template`/`link=none`/DISPLAYTITLE with nested template",
+ "setup": [
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/P0712/Parse 1",
+ "contents": "<includeonly>'''Parse 1 result:'''<br>Modify to link: [[{{{1|}}}]]<br>As-is output: {{{1|}}} '''Parse 2 result:'''<br>{{Example/P0712/Parse 2|{{{1|}}} }}</includeonly>"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "Example/P0712/Parse 2",
+ "contents": "<includeonly>Modify to link: [[{{{1|}}}]]<br>As-is output: {{{1|}}}</includeonly>"
+ },
+ {
+ "page": "Test:P0712/1",
+ "contents": "[[Issue::3853]] {{DISPLAYTITLE:Displaytitle P0712}}"
+ },
+ {
+ "page": "Test:P0712/Q.1",
+ "contents": "{{#ask: [[Issue::3853]] |link=none |template=Example/P0712/Parse 1 |format=template }}"
+ },
+ {
+ "page": "Test:P0712/Q.2",
+ "contents": "{{#ask: [[Issue::3853]] |template=Example/P0712/Parse 1 |format=template }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 `link=none`",
+ "subject": "Test:P0712/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<b>Parse 1 result:</b><br />Modify to link: <a href=\".*Test:P0712/1\" title=\"Test:P0712/1\">Test:P0712/1</a>",
+ "<b>Parse 2 result:</b><br />Modify to link: <a href=\".*Test:P0712/1\" title=\"Test:P0712/1\">Test:P0712/1 </a><br />As-is output: Test:P0712/1"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 ",
+ "subject": "Test:P0712/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<b>Parse 1 result:</b><br />Modify to link: [[<a href=\".*Test:P0712/1\" title=\"Test:P0712/1\">Displaytitle P0712</a>]]<br />",
+ "<b>Parse 2 result:</b><br />Modify to link: [[<a href=\".*/Test:P0712/1\" title=\"Test:P0712/1\">Displaytitle P0712</a> ]]"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgRestrictDisplayTitle": false,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0901.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0901.json
new file mode 100644
index 00000000..59fcd358
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0901.json
@@ -0,0 +1,112 @@
+{
+ "description": "Test #ask on moved redirected subject (#1086)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasPropertyForMove",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Page/09/01/1",
+ "contents": "[[HasPropertyForMove::ABC]]"
+ },
+ {
+ "page": "Page/09/01/2",
+ "contents": "[[HasPropertyForMove::ABC]]"
+ },
+ {
+ "move-to": {
+ "target": "Move/09/01/4",
+ "is-redirect": false
+ },
+ "page": "Page/09/01/3",
+ "contents": "[[HasPropertyForMove::ABC]]"
+ },
+ {
+ "page": "Move/09/01/Query",
+ "contents": "{{#ask:[[HasPropertyForMove::ABC]] |format=ul |link=none |headers=show }}"
+ },
+ {
+ "move-to": {
+ "target": "Redirect/09/01/2",
+ "is-redirect": true
+ },
+ "page": "Redirect/09/01/1",
+ "contents": "[[HasPropertyForMove::123]]"
+ },
+ {
+ "page": "Redirect/09/01/3",
+ "contents": "#REDIRECT [[Redirect/09/01/4]] [[HasPropertyForMove::123]]"
+ },
+ {
+ "page": "Redirect/09/01/Query",
+ "contents": "{{#ask:[[HasPropertyForMove::ABC]] OR [[HasPropertyForMove::123]] |format=ul |link=none |headers=show }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 includes move",
+ "subject": "Move/09/01/Query",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Page/09/01/1</span></span></li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Page/09/01/2</span></span></li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Move/09/01/4</span></span></li>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 includes redirect",
+ "subject": "Redirect/09/01/Query",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Page/09/01/1</span></span></li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Page/09/01/2</span></span></li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Move/09/01/4</span></span></li>",
+ "<li class=\"smw-row\"><span class=\"smw-field\"><span class=\"smw-value\">Redirect/09/01/2</span></span></li>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "mw-master": "Skipping because redirect/move causes a failure in 1.27 (#1376) with the DeferredUpdate blocking succeeding tests"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0902.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0902.json
new file mode 100644
index 00000000..c45c9e09
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0902.json
@@ -0,0 +1,65 @@
+{
+ "description": "Test #ask on failed queries to produce a `_ERRC` (#1297, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasPropertyForMove",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0902/1",
+ "contents": "{{#ask:[[Help:]] |format=ul |link=none |headers=show }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 failed NS query",
+ "subject": "Example/P0902/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 error record on empty Help:",
+ "subject": "Example/P0902/1#_ERRaefa648d070f2edc4b171586eae9b1b0",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRP",
+ "_ERRT",
+ "_SKEY"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0903.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0903.json
new file mode 100644
index 00000000..6dd0c5e9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0903.json
@@ -0,0 +1,70 @@
+{
+ "description": "Test #ask on redirected printrequest (#1290, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has PAGE",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "#REDIRECT [[Property:Has PAGE]]"
+ },
+ {
+ "page": "Example/P0903/1",
+ "contents": "[[Has page::ABC]]"
+ },
+ {
+ "page": "Example/P0903/2",
+ "contents": "[[Has PAGE::ABC]]"
+ },
+ {
+ "page": "Example/P0903/3",
+ "contents": "{{#ask:[[Has page::ABC]] |?Has page |?Has PAGE |format=table }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0903/3",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/P0903/1",
+ "Example/P0903/2"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0904.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0904.json
new file mode 100644
index 00000000..cb6327e5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0904.json
@@ -0,0 +1,98 @@
+{
+ "description": "Test #ask with subject redirected to different NS (en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0904/1",
+ "contents": "[[Has page::P0904]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "Example/P0904/1",
+ "contents": "[[Has page::P0904]]"
+ },
+ {
+ "page": "Example/P0904/1",
+ "contents": "#REDIRECT [[Help:Example/P0904/1]]"
+ },
+ {
+ "page": "Example/P0904/2",
+ "contents": "{{#ask: [[Has page::P0904]] |?Has page |format=table |link=none }}"
+ },
+ {
+ "page": "Example/P0904/3",
+ "contents": "{{#ask: [[~Example/P0904*]] |?Has page |format=table |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0904/1",
+ "namespace": "NS_HELP",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_page"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0904/2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Help:Example/P0904/1</td><td class=\"Has-page smwtype_wpg\">P0904</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (redirected subject does not appear in result list)",
+ "subject": "Example/P0904/3",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"smwtype_wpg\">Help:Example/P0904/1</td><td class=\"Has-page smwtype_wpg\">P0904</td>"
+ ],
+ "not-contain": [
+ "<td class=\"smwtype_wpg\">Example/P0904/1</td><td class=\"Has-page smwtype_wpg\">P0904</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_HELP": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0905.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0905.json
new file mode 100644
index 00000000..9a45280a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0905.json
@@ -0,0 +1,103 @@
+{
+ "description": "Test `#ask` query-in-query construct (`_sobj`/`_dat`/`_num`) (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Assessment year",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Assessment value",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Example/P0905/1",
+ "contents": "{{#subobject: |Assessment name=Assessment 1a |Assessment year=2005 |Assessment value=13 |@category=Assessment}}{{#subobject: |Assessment name=Assessment 1b |Assessment year=2006 |Assessment value=2 |@category=Assessment}}{{#subobject: |Assessment name=Assessment 1c |Assessment year=2005 |Assessment value=14 |@category=Assessment }}"
+ },
+ {
+ "page": "Example/P0905/Q1",
+ "contents": "{{#ask: [[Category:Assessment]] |?Assessment name |?Assessment year |?Assessment value }}"
+ },
+ {
+ "page": "Example/P0905/Q2",
+ "contents": "{{#ask: [[Category:Assessment]] <q>[[Assessment value::{{#ask: [[Category:Assessment]] |?Assessment value|sort=Assessment value|order=desc|limit=1 |format=plainlist |headers=hide|mainlabel=-|link=none|searchlabel=}}]] </q> |?Assessment name |?Assessment year |?Assessment value }}"
+ },
+ {
+ "page": "Example/P0905/Q3",
+ "contents": "{{#ask: [[-Has subobject::Example/P0905/1]] <q>[[Assessment value::{{#ask: [[-Has subobject::Example/P0905/1]] |?Assessment value|sort=Assessment value|order=desc|limit=1 |format=plainlist |headers=hide|mainlabel=-|link=none|searchlabel=}}]] </q> |?Assessment name |?Assessment year |?Assessment value }}"
+ },
+ {
+ "page": "Example/P0905/Q4",
+ "contents": "{{#ask: [[Category:Assessment]] <q>[[Assessment value::{{#ask: [[Category:Assessment]] |?Assessment value|sort=Assessment value|order=asc|limit=1 |format=plainlist |headers=hide|mainlabel=-|link=none|searchlabel=}}]] </q> |?Assessment name |?Assessment year |?Assessment value }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0905/Q1",
+ "assert-output": {
+ "to-contain": [
+ "Assessment 1a</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"13\"",
+ "Assessment 1b</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453736.5\">2006</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"2\"",
+ "Assessment 1c</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"14\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 ony return highest Assessment value ",
+ "subject": "Example/P0905/Q2",
+ "assert-output": {
+ "to-contain": [
+ "Assessment 1c</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"14\""
+ ],
+ "not-contain": [
+ "Assessment 1a</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"13\"",
+ "Assessment 1b</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453736.5\">2006</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"2\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 same as #1",
+ "subject": "Example/P0905/Q3",
+ "assert-output": {
+ "to-contain": [
+ "Assessment 1c</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"14\""
+ ],
+ "not-contain": [
+ "Assessment 1a</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"13\"",
+ "Assessment 1b</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453736.5\">2006</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"2\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 return only lowest Assessment value",
+ "subject": "Example/P0905/Q4",
+ "assert-output": {
+ "to-contain": [
+ "Assessment 1b</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453736.5\">2006</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"2\""
+ ],
+ "not-contain": [
+ "Assessment 1a</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"13\"",
+ "Assessment 1c</a></td><td class=\"Assessment-year smwtype_dat\" data-sort-value=\"2453371.5\">2005</td><td class=\"Assessment-value smwtype_num\" data-sort-value=\"14\""
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0906.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0906.json
new file mode 100644
index 00000000..2331bbcd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0906.json
@@ -0,0 +1,69 @@
+{
+ "description": "Test `#ask` on category/property hierarchy with circular reference (#1713, `wgContLang=en`, `wgLang=en`, 'smwgEnabledQueryDependencyLinksStore', skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "CategoryWithCircularHierarchy",
+ "contents": "[[Category:CategoryWithCircularHierarchy]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "PropertyWithCircularHierarchy",
+ "contents": "[[Subproperty of::PropertyWithCircularHierarchy]]"
+ },
+ {
+ "page": "Example/P0906/1",
+ "contents": "[[Category:CategoryWithCircularHierarchy]]"
+ },
+ {
+ "page": "Example/P0906/Q1",
+ "contents": "{{#ask: [[Category:CategoryWithCircularHierarchy]] |link=none }}"
+ },
+ {
+ "page": "Example/P0906/2",
+ "contents": "[[PropertyWithCircularHierarchy::123]]"
+ },
+ {
+ "page": "Example/P0906/Q2",
+ "contents": "{{#ask: [[PropertyWithCircularHierarchy::+]] |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0906/Q1",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0906/1"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0906/Q2",
+ "assert-output": {
+ "to-contain": [
+ "Example/P0906/2"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgEnabledQueryDependencyLinksStore": true,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/property hierarchies are currently not implemented"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0907.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0907.json
new file mode 100644
index 00000000..0367e258
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0907.json
@@ -0,0 +1,81 @@
+{
+ "description": "Test the QueryResult cache feature (#1251, `wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0907/1",
+ "contents": "[[Has page::ABC]]"
+ },
+ {
+ "page": "Example/P0907/2",
+ "contents": "{{#ask:[[Has page::ABC]] |sort=Has page |order=asc |limit=10 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0907/2",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/P0907/1"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 query from the previous #ask with same description is fetched from cache",
+ "subject": "Foo",
+ "condition": "[[Has page::ABC]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10,
+ "sort": {
+ "Has_page": "ASC"
+ }
+ },
+ "assert-queryresult": {
+ "isFromCache": true,
+ "count": 1,
+ "results": [
+ "Example/P0907/1#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQueryResultCacheType": "hash",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0908.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0908.json
new file mode 100644
index 00000000..4de6d273
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0908.json
@@ -0,0 +1,48 @@
+{
+ "description": "Test the QueryResult cache feature with different `|+lang`/`|+order` prinrequest parameters (#1251, `wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has alternative label",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "page": "Example/P0908/1",
+ "contents": "[[Category:P0908]] [[Has page::{{FULLPAGENAME}}]] [[Has alternative label::Lipase@en]], [[Has alternative label::Tributyrase@en]], [[Has alternative label::Triglyceride lipase@en]], [[Has alternative label::トリアシルグリセロールリパーゼ@ja]], [[Has alternative label::ليباز ثلاثي اسيل الغليسيرول@ar]], [[Has alternative label::Triacylglycérol lipase@fr]], [[Has alternative label::Triacilglicerol lipaza@sh]], [[Has alternative label::Triacilglicerol lipaza@sr]]"
+ },
+ {
+ "page": "Example/P0908/Q.1",
+ "contents": "{{#ask: [[Category:P0908]] |?Has alternative label|+lang=en|+order=asc |link=none }} {{#ask: [[Category:P0908]] |?Has alternative label|+lang=ja|+order=asc |link=none }} "
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (query with same signature on same page but different prinrequest parameter outputs correct content)",
+ "subject": "Example/P0908/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0908/1</td><td class=\"Has-alternative-label smwtype_txt\">Lipase<br />Tributyrase<br />Triglyceride lipase</td></tr>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/P0908/1</td><td class=\"Has-alternative-label smwtype_txt\">トリアシルグリセロールリパーゼ</td></tr>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQueryResultCacheType": "hash",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0909.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0909.json
new file mode 100644
index 00000000..42b70a8d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0909.json
@@ -0,0 +1,265 @@
+{
+ "description": "Test the description optimization (`wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`, `smwgQFilterDuplicates=true`, `smwgQueryProfiler`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/P0909/1",
+ "contents": "[[Has page::Example/P0909/1]]"
+ },
+ {
+ "page": "Example/P0909/Q.1",
+ "contents": "{{#ask: [[Has page::Example/P0909/1]] [[Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.2",
+ "contents": "{{#ask: [[Has page::Example/P0909/1]] OR [[Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.3",
+ "contents": "{{#ask: [[Has page::Example/P0909/1]] [[Has page::Example/P0909/1]] OR [[Has page::Example/P0909/1]] [[Has page::<q>[[Has page::+]]</q>]] [[Has page::+]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.4",
+ "contents": "{{#ask: [[Has page.Has page::Example/P0909/1]] OR [[Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.5",
+ "contents": "{{#ask: [[Has page.Has page::Example/P0909/1]] [[Has page.Has page.Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.6",
+ "contents": "{{#ask: [[Has page.Has page::Example/P0909/1]] [[Has page.Has page.Has page::Example/P0909/1]] OR [[Has page.Has page.Has page::Example/P0909/1]] [[Has page.Has page.Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.7",
+ "contents": "{{#ask: [[Has page.Has page::Example/P0909/1]] [[Has page.-Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.8",
+ "contents": "{{#ask: [[Has page.Has page::Example/P0909/1]] [[-Has page.Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ },
+ {
+ "page": "Example/P0909/Q.9",
+ "contents": "{{#ask: [[Has page.Has page::Example/P0909/1]] [[-Has page.Has page::Example/P0909/1]] OR [[Has page.-Has page::Example/P0909/1]] |limit=50 |offset=0 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0909/Q.1#_QUERYced3dc3308e03e4ff0c92578d616e6a5",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[[Has page::Example/P0909/1]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "subject": "Example/P0909/Q.2#_QUERYced3dc3308e03e4ff0c92578d616e6a5",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[[Has page::Example/P0909/1]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2",
+ "subject": "Example/P0909/Q.3#_QUERY84456d5e55da8a3ba2279a5eb73ce483",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "<q> <q>[[Has page::Example/P0909/1]]</q> OR [[Has page::Example/P0909/1]] [[Has page.Has page::+]] [[Has page::+]]</q>"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3",
+ "subject": "Example/P0909/Q.4#_QUERYcdd649eae7a93d114d44b75d9c1ed65c",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "<q> <q>[[Has page.Has page::Example/P0909/1]]</q> OR <q>[[Has page::Example/P0909/1]]</q> </q>"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4",
+ "subject": "Example/P0909/Q.5#_QUERY13b773c8ea18d4839f069a8a88dbe783",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[[Has page.Has page::Example/P0909/1]] [[Has page.Has page.Has page::Example/P0909/1]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5",
+ "subject": "Example/P0909/Q.6#_QUERYfb6756e6bb1d5cf0c37b0c305caf6d6e",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "<q>[[Has page.Has page::Example/P0909/1]] [[Has page.Has page.Has page::Example/P0909/1]] OR <q>[[Has page.Has page.Has page::Example/P0909/1]]</q> </q>"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#6",
+ "subject": "Example/P0909/Q.7#_QUERYbcb06ea6a827c21b2ae2fbc8359bef8c",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[[Has page.Has page::Example/P0909/1]] [[Has page.-Has page::Example/P0909/1]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#7",
+ "subject": "Example/P0909/Q.8#_QUERYecd911af9ce2cf69bacfbab3041114c7",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "[[Has page.Has page::Example/P0909/1]] [[-Has page.Has page::Example/P0909/1]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#8",
+ "subject": "Example/P0909/Q.9#_QUERY69098f6e24f5bf124fec18d6339450ce",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "<q>[[Has page.Has page::Example/P0909/1]] [[-Has page.Has page::Example/P0909/1]] OR <q>[[Has page.-Has page::Example/P0909/1]]</q> </q>"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQueryProfiler": true,
+ "smwgQFilterDuplicates": true,
+ "smwgQueryResultCacheType": "hash",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0910.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0910.json
new file mode 100644
index 00000000..1dabdeca
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0910.json
@@ -0,0 +1,134 @@
+{
+ "description": "Test `#ask` to highlight (`#-hl`) search token in result set (#..., `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has mono text",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record with text",
+ "contents": "[[Has type::Record]] [[Has fields::Text;Number]]"
+ },
+ {
+ "page": "Example/P0910/1",
+ "contents": "[[Category:P0910]] [[Has text::Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ...]]"
+ },
+ {
+ "page": "Example/P0910/Q.1",
+ "contents": "{{#ask: [[Has text::~*dolor sit amet consectetuer*]] |?Has text#-hl |link=none }} "
+ },
+ {
+ "page": "Example/P0910/2",
+ "contents": "[[Category:P0910]] [[Has mono text::Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ...@la]]"
+ },
+ {
+ "page": "Example/P0910/Q.2.1",
+ "contents": "{{#ask: [[Has mono text::~*dolor sit amet consectetuer*]] |?Has mono text#-hl |link=none }} "
+ },
+ {
+ "page": "Example/P0910/Q.2.2",
+ "contents": "{{#ask: [[Has mono text::~*dolor sit amet consectetuer*]] |?Has mono text#-hl|+lang=la |link=none }} "
+ },
+ {
+ "page": "Example/P0910/Q.2.3",
+ "contents": "{{#ask: [[Has mono text::~*dolor sit amet consectetuer*]] |?Has mono text#-hl|+index=1 |link=none }} "
+ },
+ {
+ "page": "Example/P0910/3",
+ "contents": "[[Category:P0910]] [[Has record with text::Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ...;123]]"
+ },
+ {
+ "page": "Example/P0910/Q.3.1",
+ "contents": "{{#ask: [[Has record with text::~*dolor sit amet consectetuer*]] |?Has record with text#-hl |link=none }} "
+ },
+ {
+ "page": "Example/P0910/Q.3.2",
+ "contents": "{{#ask: [[Has record with text::~*dolor sit amet consectetuer*]] |?Has record with text#-hl|+index=1 |link=none }} "
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (...)",
+ "subject": "Example/P0910/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_txt\">Lorem ipsum <b>dolor</b> <b>sit</b> <b>amet</b> <b>consectetuer</b> justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ..."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (simple record/mono text doens't display a highlight)",
+ "subject": "Example/P0910/Q.2.1",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_mlt_rec\">Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ... (la)"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (on selected language |+lang, tokens are displayed)",
+ "subject": "Example/P0910/Q.2.2",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_txt\">Lorem ipsum <b>dolor</b> <b>sit</b> <b>amet</b> <b>consectetuer</b> justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ..."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (on selected index |+index, tokens are displayed)",
+ "subject": "Example/P0910/Q.2.3",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_txt\">Lorem ipsum <b>dolor</b> <b>sit</b> <b>amet</b> <b>consectetuer</b> justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ..."
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (simple record/mono text doens't display a highlight)",
+ "subject": "Example/P0910/Q.3.1",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_rec\">Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ... (123)"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#5 (on selected index |+index, tokens are displayed)",
+ "subject": "Example/P0910/Q.3.2",
+ "assert-output": {
+ "to-contain": [
+ "smwtype_txt\">Lorem ipsum <b>dolor</b> <b>sit</b> <b>amet</b> <b>consectetuer</b> justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede lorem nulla justo diam wisi. Libero Nam turpis ..."
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0911.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0911.json
new file mode 100644
index 00000000..bf021791
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0911.json
@@ -0,0 +1,64 @@
+{
+ "description": "Test the `_ASK` profile (#2270, `smwgQueryProfiler`, `smwgQueryResultCacheType`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P0911/1",
+ "contents": "[[Has page::Example/P0911/1]]"
+ },
+ {
+ "page": "Example/P0911/Q.1",
+ "contents": "{{#ask: [[Has page::Example/P0911/1]] |limit=50 |offset=0 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0911/Q.1#_QUERY7f8c02d826a5987a65a9de7ba8d9abfd",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 7,
+ "propertyKeys": [
+ "_ASKST",
+ "_ASKFO",
+ "_ASKSI",
+ "_ASKDE",
+ "_ASKDU",
+ "_ASKPA",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "{\"limit\":50,\"offset\":0,\"sort\":[\"\"],\"order\":[\"asc\"],\"mode\":1}"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQueryResultCacheType": "hash",
+ "smwgQueryProfiler" : [
+ "SMW_QPRFL_DUR",
+ "SMW_QPRFL_PARAMS"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0912.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0912.json
new file mode 100644
index 00000000..7628fc47
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0912.json
@@ -0,0 +1,171 @@
+{
+ "description": "Test `#ask` with (`#-raw`) formatter using `#set` (#..., `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has mono text",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "page": "Example/P0912/1",
+ "contents": "[[Category:P0912]] {{#set: Has text=Some text with annotation [[Foo::Example/P0912/1]] }}"
+ },
+ {
+ "page": "Example/P0912/Q.1",
+ "contents": "{{#ask: [[Category:P0912]] [[Has text::+]] |?Has text |link=none }}"
+ },
+ {
+ "page": "Example/P0912/Q.2",
+ "contents": "{{#ask: [[Category:P0912]] [[Has text::+]] |?Has text#-raw |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0912/1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_INST",
+ "_SKEY",
+ "Has text"
+ ],
+ "propertyValues": [
+ "Some text with annotation [[Foo::Example/P0912/1]]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31-) (without `-raw`)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0912/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation Example/P0912/1</td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31+) (without `-raw`)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0912/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation Example/P0912/1</td></tr></tbody></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31-) (with `-raw`)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0912/Q.2",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY",
+ "Foo"
+ ],
+ "propertyValues": [
+ "Example/P0912/1"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation",
+ "title=\"Example/P0912/1\">Example/P0912/1</a></td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31+) (with `-raw`)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0912/Q.2",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY",
+ "Foo"
+ ],
+ "propertyValues": [
+ "Example/P0912/1"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation",
+ "title=\"Example/P0912/1\">Example/P0912/1</a></td></tr></tbody></table>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0913.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0913.json
new file mode 100644
index 00000000..afa991b1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0913.json
@@ -0,0 +1,221 @@
+{
+ "description": "Test `#ask` with (`#-raw`) formatter with links in values (#..., `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::text]]"
+ },
+ {
+ "page": "Example/P0913/1",
+ "contents": "[[Category:P0913]] [[Has text::Some text with annotation [[Foo::Example/P0913/1]]]]"
+ },
+ {
+ "page": "Example/P0913/Q.1",
+ "contents": "{{#ask: [[Category:P0913]] [[Has text::+]] |?Has text |link=none }}"
+ },
+ {
+ "page": "Example/P0913/Q.2",
+ "contents": "{{#ask: [[Category:P0913]] [[Has text::+]] |?Has text#-raw |link=none }}"
+ },
+ {
+ "page": "Example/P0913/Q.3",
+ "contents": "{{#ask: [[Category:P0913]] [[Has text::+]] |?Has text#-raw |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/P0913/1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 5,
+ "propertyKeys": [
+ "_MDAT",
+ "_INST",
+ "_SKEY",
+ "Has text",
+ "Foo"
+ ],
+ "propertyValues": [
+ "Some text with annotation Example/P0913/1"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31-) (without `-raw`)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0913/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation <a href=",
+ "title=\"Example/P0913/1\">Example/P0913/1</a></td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (1.31+) (without `-raw`)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0913/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation <a href=",
+ "title=\"Example/P0913/1\">Example/P0913/1</a></td></tr></tbody></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31-) (with `-raw`)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0913/Q.2",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation <a href=",
+ "title=\"Example/P0913/1\">Example/P0913/1</a></td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (1.31+) (with `-raw`)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0913/Q.2",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation <a href=",
+ "title=\"Example/P0913/1\">Example/P0913/1</a></td></tr></tbody></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (1.31-) same as #2 (with deprecated `-ia`)",
+ "skip-on": {
+ "mediawiki": [ ">1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0913/Q.3",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation <a href=",
+ "title=\"Example/P0913/1\">Example/P0913/1</a></td></tr></table>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (1.31+) same as #2 (with deprecated `-ia`)",
+ "skip-on": {
+ "mediawiki": [ "<1.30.x", "MediaWiki changed the HTML Tidy" ]
+ },
+ "subject": "Example/P0913/Q.3",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-text smwtype_txt\">Some text with annotation <a href=",
+ "title=\"Example/P0913/1\">Example/P0913/1</a></td></tr></tbody></table>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgParserFeatures": [
+ "SMW_PARSER_STRICT",
+ "SMW_PARSER_INL_ERROR",
+ "SMW_PARSER_HID_CATS",
+ "SMW_PARSER_LINV"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0914.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0914.json
new file mode 100644
index 00000000..b54ed263
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0914.json
@@ -0,0 +1,88 @@
+{
+ "description": "Test the description optimization on `_ref_rec` type with property chain query/sort (`wgContLang=en`, `wgLang=en`, `smwgQueryResultCacheType=true`, `smwgQFilterDuplicates=true`, `smwgQueryProfiler`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "ID",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Runtime",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Memory used",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Runtime benchmark",
+ "contents": "[[Has type::Reference]] [[Has fields::Date; Version; Memory used; Runtime;ID;Benchmark notes]]"
+ },
+ {
+ "page": "Example/P0914/1",
+ "contents": "{{#subobject: |Runtime benchmark=27 Nov 2016;0583b05;16690400;48.35;200;n/a }}"
+ },
+ {
+ "page": "Example/P0914/Q.1",
+ "contents": "{{#ask: [[Runtime benchmark.ID::+]] |?Runtime benchmark |?Runtime benchmark.Memory used#- |?Runtime benchmark.ID |?Runtime benchmark.Runtime|?Runtime benchmark.Benchmark notes |format=broadtable |sort=Runtime benchmark.ID,Runtime benchmark.Runtime |order=desc |limit=2 |link=none }}"
+ },
+ {
+ "page": "Example/P0914/Q.2",
+ "contents": "{{#ask: [[Runtime benchmark.ID::+]] OR [[Runtime benchmark.Runtime::+]] <q> [[Runtime benchmark.ID::+]]</q> |?Runtime benchmark |?Runtime benchmark.Memory used#- |?Runtime benchmark.ID |?Runtime benchmark.Runtime|?Runtime benchmark.Benchmark notes |format=broadtable |sort=Runtime benchmark.ID,Runtime benchmark.Runtime |order=desc |limit=2 |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (no `Error: 1066 Not unique table/alias ...`)",
+ "subject": "Example/P0914/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_ASK",
+ "_SKEY"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Runtime-benchmark smwtype_ref_rec\">27 November 2016</td><td class=\"Memory-used smwtype_num\" data-sort-value=\"16690400\">16690400</td><td class=\"ID smwtype_num\" data-sort-value=\"200\">200</td><td class=\"Runtime smwtype_num\" data-sort-value=\"48.35\">48.35</td><td class=\"Benchmark-notes smwtype_wpg\">N/a</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#0 (no `Error: 1066 Not unique table/alias ...`)",
+ "subject": "Example/P0914/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Runtime-benchmark smwtype_ref_rec\">27 November 2016</td><td class=\"Memory-used smwtype_num\" data-sort-value=\"16690400\">16690400</td><td class=\"ID smwtype_num\" data-sort-value=\"200\">200</td><td class=\"Runtime smwtype_num\" data-sort-value=\"48.35\">48.35</td><td class=\"Benchmark-notes smwtype_wpg\">N/a</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQFilterDuplicates": true,
+ "smwgQueryResultCacheType": "hash",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0915.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0915.json
new file mode 100644
index 00000000..413e9740
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0915.json
@@ -0,0 +1,112 @@
+{
+ "description": "Test category redirect (`SMW_CAT_REDIRECT`)",
+ "setup": [
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Example/P0915",
+ "contents": "#REDIRECT [[Example/P0915/1]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Example/P0915/SubCat",
+ "contents": "[[Category:Example/P0915]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Example/P0915/ValidCat",
+ "contents": "#REDIRECT [[:Category:Example/P0915/ValidCat2]]"
+ },
+ {
+ "page": "Example/P0915/1",
+ "contents": "[[Category:Example/P0915]]"
+ },
+ {
+ "page": "Example/P0915/2",
+ "contents": "[[Category:Example/P0915/ValidCat]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 track category with invalid (NS_MAIN) redirect target",
+ "subject": "Example/P0915/1",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 track sub-category",
+ "namespace": "NS_CATEGORY",
+ "subject": "Example/P0915/SubCat",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_ERRC"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 valid cat redirect, dsiplay the redirect target",
+ "subject": "Example/P0915/2",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "_INST"
+ ],
+ "propertyValues": [
+ "Example/P0915/ValidCat2#14##"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgCategoryFeatures": [
+ "SMW_CAT_INSTANCE",
+ "SMW_CAT_REDIRECT",
+ "SMW_CAT_HIERARCHY"
+ ],
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0916.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0916.json
new file mode 100644
index 00000000..6244483a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-0916.json
@@ -0,0 +1,62 @@
+{
+ "description": "Test `_ref_rec` with a `_eid` field (#2985)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "WDID",
+ "contents": "[[Has type::External identifier]][[External formatter uri::https://www.wikidata.org/entity/$1]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "WD reference",
+ "contents": "[[Has type::Reference]] [[Has fields::URL;WDID]]"
+ },
+ {
+ "page": "Example/P0916/1",
+ "contents": "[[WD reference::https://en.wikipedia.org/wiki/Franz_Schubert;Q7312]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (correct formatting for external identifier)",
+ "subject": "Example/P0916/1",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "WD reference"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "data-content=\"&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;.*:WDID&quot;",
+ "title=&quot;.*:WDID&quot;&gt;WDID&lt;/a&gt;: &lt;a href=&quot;https://www.wikidata.org/entity/Q7312&quot; target=&quot;_blank&quot;&gt;Q7312&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;\" title=\"WDID: Q7312\">"
+ ],
+ "not-contain": [
+ "title=&quot;.*:WDID&quot;&gt;WDID&lt;/a&gt;: &lt;span class=&quot;plainlinks smw-eid&quot;&gt;<a rel=\"nofollow\" class=\"external text\" href=\"https://www.wikidata.org/entity/Q7312\">Q7312</a>&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;\" title=\"WDID: <a rel=\"nofollow\" class=\"external text\" href=\"https://www.wikidata.org/entity/Q7312\">Q7312</a>\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1000.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1000.json
new file mode 100644
index 00000000..52a5271c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1000.json
@@ -0,0 +1,127 @@
+{
+ "description": "Test property page with redirect(synonym)/displayTitle (`wgContLang=en`, `wgLang=en`, `wgAllowDisplayTitle`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has synonym",
+ "contents": "[[Has type::Page]] {{DISPLAYTITLE:SomeTest}}"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Some redirect",
+ "contents": "[[Has type::Page]] {{DISPLAYTITLE:SomePropertyRedirectTest}}"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Some redirect",
+ "contents": "#REDIRECT [[Property:Has synonym]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Some redirect2",
+ "contents": "[[Has type::Page]] {{DISPLAYTITLE:IsRedirectTarget}}"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Some redirect2",
+ "contents": "[[Has type::Page]] {{DISPLAYTITLE:SomeTest2}}",
+ "move-to":{
+ "target": "Has synonym2",
+ "is-redirect": true
+ }
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (manual redirect)",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has synonym",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_TYPE",
+ "_MDAT",
+ "_DTITLE",
+ "_SKEY"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI"
+ ],
+ "propertyValues": [
+ "Some_redirect#102##"
+ ]
+ }
+ }
+ },
+ "assert-output": {
+ "onPageView": true,
+ "to-contain": [
+ "class=\"mw-redirect\" title=\"Property:Some redirect\">Property:Some redirect</a>"
+ ],
+ "not-contain": [
+ "class=\"mw-redirect\" title=\"Property:Some redirect\">SomeTest</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has synonym2",
+ "store": {
+ "clear-cache": true
+ },
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 4,
+ "propertyKeys": [
+ "_TYPE",
+ "_MDAT",
+ "_DTITLE",
+ "_SKEY"
+ ],
+ "incoming": {
+ "propertyKeys": [
+ "_REDI"
+ ],
+ "propertyValues": [
+ "Some_redirect2#102##"
+ ]
+ }
+ }
+ },
+ "assert-output": {
+ "onPageView": true,
+ "to-contain": [
+ "class=\"mw-redirect\" title=\"Property:Some redirect2\">Property:Some redirect2</a>"
+ ],
+ "not-contain": [
+ "class=\"mw-redirect\" title=\"Property:Some redirect2\">SomeTest2</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgAllowDisplayTitle": true,
+ "wgRestrictDisplayTitle": false,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1001.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1001.json
new file mode 100644
index 00000000..7f4135f6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1001.json
@@ -0,0 +1,97 @@
+{
+ "description": "Test property page with parameters (#2479, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page test",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P1001/1",
+ "contents": "[[Has page test::One]]"
+ },
+ {
+ "page": "Example/P1001/2",
+ "contents": "[[Has page test::Two]]"
+ },
+ {
+ "page": "Example/P1001/3",
+ "contents": "[[Has page test::Foo]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has page test",
+ "assert-output": {
+ "onPageView": {
+ "parameters": {
+ "limit": "1",
+ "offset": "1"
+ }
+ },
+ "to-contain": [
+ "Has_page_test&amp;limit=1&amp;offset=0",
+ "title=\"Example/P1001/2\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (see issue #2479)",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has page test",
+ "assert-output": {
+ "onPageView": {
+ "parameters": {
+ "limit": "1foo",
+ "offset": "1"
+ }
+ },
+ "to-contain": [
+ "Has_page_test&amp;limit=1&amp;offset=0",
+ "title=\"Example/P1001/2\""
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (use a filter, #2878)",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has page test",
+ "assert-output": {
+ "onPageView": {
+ "parameters": {
+ "filter": "Foo"
+ }
+ },
+ "to-contain": [
+ "=&amp;filter=Foo",
+ "title=\"Example/P1001/3\""
+ ],
+ "not-contain": [
+ "Example/P1001/1",
+ "Example/P1001/2"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1002.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1002.json
new file mode 100644
index 00000000..d938ae36
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1002.json
@@ -0,0 +1,44 @@
+{
+ "description": "Test property page with improper assignment list (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "page": "Example/P1002/1",
+ "contents": "[[Has number::abc]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has number",
+ "assert-output": {
+ "onPageView": true,
+ "to-contain": [
+ "<ul><li><a href=\".*Example/P1002/1#_ERR825bfe376713b81d8177c7353181ec6e\".*title=\"Special:Browse/:Example-2FP1002-2F1-23-5FERR825bfe376713b81d8177c7353181ec6e\">+</a></span></li></ul>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1003.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1003.json
new file mode 100644
index 00000000..78d75e0e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1003.json
@@ -0,0 +1,72 @@
+{
+ "description": "Test property restriction on annotation and #ask (`wgContLang=en`, `wgLang=en`, `smwgCreateProtectionRight`)",
+ "setup": [
+ {
+ "page": "Example/P1003/1",
+ "contents": "[[Has unknown::abc]]"
+ },
+ {
+ "page": "Example/P1003/2",
+ "contents": "{{#ask: [[Has unknown::123]] |format=table |limit=10 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 on annotation attempt",
+ "subject": "Example/P1003/1#_ERR504f58c6ccf85a3bb8ccd4562463664a",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRP",
+ "_ERRT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "Has_unknown#102##",
+ "[8,\"smw-datavalue-property-create-restriction\",\"Has unknown\",\"foo\"]"
+ ]
+ }
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 on #ask attempt",
+ "subject": "Example/P1003/2#_ERR85d779fcd4429a44d5f9dd85e292a953",
+ "assert-store": {
+ "semantic-data": {
+ "strict-mode-valuematch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_ERRP",
+ "_ERRT",
+ "_SKEY"
+ ],
+ "propertyValues": [
+ "Has_unknown#102##",
+ "[2,\"smw-datavalue-property-create-restriction\",\"Has unknown\",\"foo\"]"
+ ]
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgCreateProtectionRight": "foo",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1004.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1004.json
new file mode 100644
index 00000000..f1b50279
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1004.json
@@ -0,0 +1,59 @@
+{
+ "description": "Test different default output formatter `_dat` (`smwgDefaultOutputFormatters`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date 2",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/P1004/1",
+ "contents": "[[Has date::1 Jan 1970]] [[Has date 2::2 Jan 2000]] [[Category:P1004]]"
+ },
+ {
+ "page": "Example/P1004/Q.1",
+ "contents": "{{#ask: [[Category:P1004]] |?Modification date |?Has date |?Has date 2 |?Has date#ISO |limit=10 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (all `_dat` (Has date 2) -> JD, `_MDAT` (Modification date) -> ISO, First `Has date` -> MEDIAWIKI, Second `Has date` overrides default with ISO)",
+ "subject": "Example/P1004/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Modification-date smwtype_dat\" data-sort-value=.*T.*</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2440587.5\">1 January 1970</td>",
+ "<td class=\"Has-date-2 smwtype_dat\" data-sort-value=\"2451545.5\">2451545.5</td>",
+ "<td class=\"Has-date smwtype_dat\" data-sort-value=\"2440587.5\">1970-01-01</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgDefaultOutputFormatters": {
+ "_dat": "JD",
+ "_MDAT": "ISO",
+ "Has date": "MEDIAWIKI"
+ },
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1005.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1005.json
new file mode 100644
index 00000000..0a371487
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1005.json
@@ -0,0 +1,53 @@
+{
+ "description": "Test property page with parameters/sort",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page test",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P1005/A",
+ "contents": "[[Has page test::Sort]] {{DEFAULTSORT:XXX}}"
+ },
+ {
+ "page": "Example/P1005/B",
+ "contents": "[[Has page test::Sort]] {{DEFAULTSORT:AAA}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (use a filter with correct sorting )",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has page test",
+ "assert-output": {
+ "onPageView": {
+ "parameters": {
+ "filter": "Sort"
+ }
+ },
+ "to-contain": [
+ "<div class=\"smw-table-cell header-title\"><div id=\"A\">A</div>.*<div class=\"smw-table-cell smwpropname\" data-list-index=\"0\"><a href=\".*/Example/P1005/B\" title=\"Example/P1005/B\">Example/P1005/B</a>",
+ "<div class=\"smw-table-cell header-title\"><div id=\"X\">X</div>.*<div class=\"smw-table-cell smwpropname\" data-list-index=\"1\"><a href=\".*/Example/P1005/A\" title=\"Example/P1005/A\">Example/P1005/A</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1006.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1006.json
new file mode 100644
index 00000000..1ad73906
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1006.json
@@ -0,0 +1,78 @@
+{
+ "description": "Test property page sorting (`wgRestrictDisplayTitle`, `smwgEntityCollation`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page test",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P1006/1",
+ "contents": "[[Has page test::123]] {{DISPLAYTITLE:AA}}"
+ },
+ {
+ "page": "Example/P1006/2",
+ "contents": "[[Has page test::123]] {{DISPLAYTITLE:AA}} {{#subobject: |Has page test=456 |@sortkey=AA}}"
+ },
+ {
+ "page": "Example/P1006/3",
+ "contents": "[[Has page test::123]] {{DISPLAYTITLE:BB}}"
+ },
+ {
+ "page": "Example/P1006/4",
+ "contents": "[[Has page test::123]] {{DISPLAYTITLE:CC}} {{#subobject: |Has page test=456 |@sortkey=BB}}"
+ },
+ {
+ "page": "Example/P1006/5",
+ "contents": "[[Has page test::123]] {{DISPLAYTITLE:DD}} {{#subobject: |Has page test=456 |@sortkey=DD}}"
+ },
+ {
+ "page": "Example/P1006/6",
+ "contents": "[[Has page test::123]] {{DISPLAYTITLE:DD}} {{#subobject: |Has page test=456 |@sortkey=DD}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (verify item list order)",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has page test",
+ "assert-output": {
+ "onPageView": {
+ "parameters": {}
+ },
+ "to-contain": [
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"0\"><a href=.*Example/P1006/1\" title=\"Example/P1006/1\">AA</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"1\"><a href=.*Example/P1006/2\" title=\"Example/P1006/2\">AA</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"2\"><a href=.*Example/P1006/2#_14d8b802a338f5900237277114a2cc2f\" .*title=\"Example/P1006/2\".*>AA</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"3\"><a href=.*Example/P1006/3\" title=\"Example/P1006/3\">BB</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"4\"><a href=.*Example/P1006/4#_6961cf334b7bc5632473cf15ebfc3094\" .*title=\"Example/P1006/4\".*>CC</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"5\"><a href=.*Example/P1006/4\" title=\"Example/P1006/4\">CC</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"6\"><a href=.*Example/P1006/5\" title=\"Example/P1006/5\">DD</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"7\"><a href=.*Example/P1006/5#_e4e502c29803cb65c90fa99b6abd99da\" .*title=\"Example/P1006/5\".*>DD</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"8\"><a href=.*Example/P1006/6\" title=\"Example/P1006/6\">DD</a>",
+ "<div class=\"smw-table-cell smwpropname\" data-list-index=\"9\"><a href=.*Example/P1006/6#_e4e502c29803cb65c90fa99b6abd99da\" .*title=\"Example/P1006/6\".*>DD</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgAllowDisplayTitle": true,
+ "wgRestrictDisplayTitle": false,
+ "smwgEntityCollation": "identity",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1007.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1007.json
new file mode 100644
index 00000000..4d2a2243
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/p-1007.json
@@ -0,0 +1,57 @@
+{
+ "description": "Test sorting on Pages will not exclude non-existent pages from result (#540)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "knows page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/P1007/1",
+ "contents": "[[knows page::Example/P1007/Ref 3]]"
+ },
+ {
+ "page": "Example/P1007/2",
+ "contents": "[[knows page::Example/P1007/Ref 2]]"
+ },
+ {
+ "page": "Example/P1007/3",
+ "contents": "[[knows page::Example/P1007/Ref 1]]"
+ },
+ {
+ "page": "Example/P1007/Ref 1",
+ "contents": "SomeContent"
+ },
+ {
+ "page": "Example/P1007/Ref 3",
+ "contents": "SomeContent"
+ },
+ {
+ "page": "Example/P1007/Test",
+ "contents": "{{#ask:[[knows page::+]]|?knows page |sort=knows page|format=plainlist}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (verify pages referencing non-existent pages are included in the result)",
+ "subject": "Example/P1007/Test",
+ "assert-output": {
+ "to-contain": "Example/P1007/3.*Example/P1007/2.*Example/P1007/1"
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0101.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0101.json
new file mode 100644
index 00000000..cc56a50b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0101.json
@@ -0,0 +1,127 @@
+{
+ "description": "Test `_txt` query for simple assignments, NS_HELP, and special chars",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has blob property",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has another blob property",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "abc-123&^*",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Examples/Q0101/1",
+ "contents": "[[Has blob property::Value One]], [[Has another blob property::Value One]]"
+ },
+ {
+ "page": "Examples/Q0101/2",
+ "namespace": "NS_HELP",
+ "contents": "[[Has blob property::Value Two]], [[Has another blob property::Value Two]]"
+ },
+ {
+ "page": "Examples/Q0101/3",
+ "contents": "[[Has text::foo-123#&^*%<1?=/->\"']]"
+ },
+ {
+ "page": "Examples/Q0101/4",
+ "contents": "[[abc-123&^*::foo-123#&^*%<1?=/->\"']]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 Simple disjunctive blob query",
+ "condition": "[[Has blob property::Value One]] OR [[Has another blob property::Value Two]]",
+ "printouts": [
+ "Has blob property"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Examples/Q0101/1#0##",
+ "Examples/Q0101/2#12##"
+ ],
+ "count": "2",
+ "dataitems": [
+ {
+ "type": "_txt",
+ "value": "Value Two"
+ },
+ {
+ "type": "_txt",
+ "value": "Value One"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 Simple conjunctive blob query",
+ "condition": "[[Has blob property::Value One]][[Has another blob property::Value One]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Examples/Q0101/1#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 with special chars",
+ "condition": "[[Has text::foo-123#&^*%<1?=/->\"']]",
+ "parameters" : {
+ "limit" : "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Examples/Q0101/3#0##"
+ ],
+ "count": 1
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 with special chars",
+ "condition": "[[abc-123&^*::foo-123#&^*%<1?=/->\"']]",
+ "parameters" : {
+ "limit" : "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Examples/Q0101/4#0##"
+ ],
+ "count": 1
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_HELP": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0102.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0102.json
new file mode 100644
index 00000000..e8d8fed6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0102.json
@@ -0,0 +1,263 @@
+{
+ "description": "Test `_txt` for `~*` regex queries to validate correct escape pattern as applied in the `QueryEngine`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has FirstRegexBlobSearchProperty",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has SecondRegexBlobSearchProperty",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern",
+ "contents": "[[Has FirstRegexBlobSearchProperty::{(+*. \\;)}]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern",
+ "contents": "{{#set:|Has FirstRegexBlobSearchProperty=[(*. \\=^)\"]}} {{#subobject:|Has SecondRegexBlobSearchProperty=[(+. \\:)]-|}}"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "RequiresSuperSpecialEscapePattern",
+ "contents": "{{#set:|Has FirstRegexBlobSearchProperty=Foo(\"#^$&-/)-|}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 Left curly brackets",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*{*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 Right curly brackets",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*}*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 Left parenthesis",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*(*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##",
+ "RequiresSuperSpecialEscapePattern#0##",
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "3"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 Disjunctive left parenthesis",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*(*]] OR [[Has SecondRegexBlobSearchProperty::~*(*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##",
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##",
+ "RequiresSuperSpecialEscapePattern#0##",
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##_4726701f0e7d838d922ac6b9414558dc"
+ ],
+ "count": "4"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 Right parenthesis",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*)*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##",
+ "RequiresSuperSpecialEscapePattern#0##",
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "3"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 Disjunctive right parenthesis",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*)*]] OR [[Has SecondRegexBlobSearchProperty::~*)*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##",
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##",
+ "RequiresSuperSpecialEscapePattern#0##",
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##_4726701f0e7d838d922ac6b9414558dc"
+ ],
+ "count": "4"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 Left square brackets",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*[*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 Right square brackets",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*]*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*;?}]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9",
+ "condition": "[[Has SecondRegexBlobSearchProperty::~*+.*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##_4726701f0e7d838d922ac6b9414558dc"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*=^*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#11 Composite regex search",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*{*]][[Has FirstRegexBlobSearchProperty::~*}*]][[Has FirstRegexBlobSearchProperty::~*)*]] OR [[Has SecondRegexBlobSearchProperty::~*)*]] OR [[Has FirstRegexBlobSearchProperty::~*=^*]][[Has SecondRegexBlobSearchProperty::~*+.*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RegexTextAnnotationForCharactersThatRequireSpecialEscapePattern#0##",
+ "RegexParserAnnotationForCharactersThatRequireSpecialEscapePattern#0##_4726701f0e7d838d922ac6b9414558dc"
+ ],
+ "count": "2"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#12 Pipe regex",
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*-|*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RequiresSuperSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#13 Requires special escaping effort",
+ "skip-on": {
+ "elastic": "`/` would require escaping but at the same would make it invisible to be used as subpage Foo/Boo divider on other searches"
+ },
+ "condition": "[[Has FirstRegexBlobSearchProperty::~*Foo(\"#^$&-/)-|*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "RequiresSuperSpecialEscapePattern#0##"
+ ],
+ "count": "1"
+ }
+ }
+ ],
+ "settings": {
+ "smwgQMaxSize": "25"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0103.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0103.json
new file mode 100644
index 00000000..7f31069c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0103.json
@@ -0,0 +1,223 @@
+{
+ "description": "Test `_txt` for `~*` regex query with the condition to include the `\\` escape character (skip sqlite, postgres)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has regexblob property",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has simple text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Escape character blob subject-a",
+ "contents": "{{#set:|Has regexblob property=[(+*. \\.)']}} {{#subobject:FixedSubobjectName|Has regexblob property=[(+* \\:)]\\\\\"}}"
+ },
+ {
+ "page": "Escape character blob subject-b",
+ "contents": "{{#set:|Has regexblob property=[(+*. \\;)\\\\']\\\"}} {{#subobject:FixedSubobjectName|Has regexblob property=[(+* \\=)]\\\\\"\\\"}}"
+ },
+ {
+ "page": "Escape character blob subject-c",
+ "contents": "[[Has regexblob property::Foo(\\\"'#^$&-/)]]"
+ },
+ {
+ "page": "BlobValue with whitespaces",
+ "contents": "[[Has simple text:: +/-nuclear atypia ]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has regexblob property::~*.*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-a#0##",
+ "Escape character blob subject-b#0##"
+ ],
+ "count": "2"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has regexblob property::~*\\'*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-b#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Has regexblob property::~*'*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-b#0##",
+ "Escape character blob subject-a#0##",
+ "Escape character blob subject-c#0##"
+ ],
+ "count": "3"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Has regexblob property::~*\\\\'*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-b#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Has regexblob property::~*\\\\\"*]]",
+ "printouts": [
+ "Has regexblob property"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-a#0##FixedSubobjectName",
+ "Escape character blob subject-b#0##FixedSubobjectName"
+ ],
+ "count": "2"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[Has regexblob property::~*\\\\\"\\\"*]]",
+ "skip-on": {
+ "elastic": "Finding more than one due to the wildcard"
+ },
+ "printouts": [
+ "Has regexblob property"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-b#0##FixedSubobjectName"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6",
+ "condition": "[[Has regexblob property::~*\\\"*]]",
+ "printouts": [
+ "Has regexblob property"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-a#0##FixedSubobjectName",
+ "Escape character blob subject-b#0##",
+ "Escape character blob subject-b#0##FixedSubobjectName",
+ "Escape character blob subject-c#0##"
+ ],
+ "count": "4"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7",
+ "condition": "[[Has regexblob property::~*\\.*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-a#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8",
+ "condition": "[[Has regexblob property::~*\\:*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-a#0##FixedSubobjectName"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9",
+ "condition": "[[Has regexblob property::~*Foo(\\\"'#^$&-/)*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Escape character blob subject-c#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10 find subject even when value annotation contained whitespaces",
+ "condition": "[[Has simple text::+/-nuclear atypia]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "BlobValue with whitespaces#0##"
+ ],
+ "count": "1"
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "skip-on": {
+ "sqlite": "Requires special \\ escape sequence on sqlite"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0104.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0104.json
new file mode 100644
index 00000000..9e863e0f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0104.json
@@ -0,0 +1,274 @@
+{
+ "description": "Test `_txt`/`~` with enabled full-text search support (only enabled for MySQL, SQLite)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/Q0104/1",
+ "contents": "{{#subobject: |Has text=MySQL vs MariaDB database}} {{#subobject: |Has text=Oracle vs MariaDB database}} {{#subobject: |Has text=PostgreSQL vs MariaDB database and more of}} {{#subobject: |Has text=MariaDB overview}}"
+ },
+ {
+ "page": "Example/Q0104/2",
+ "contents": "{{#subobject: |Has text=Elastic search}} {{#subobject: |Has text=Sphinx search}}"
+ },
+ {
+ "page": "Example/Q0104/3",
+ "contents": "{{#subobject: |Has text=...a hyphenated phrase that has special significance when it appears at the beginning of text...}} {{#subobject: |Has text=...a hyphenated phrase that has NOT any special significance when it appears at the beginning of text...}}"
+ },
+ {
+ "page": "Example/Q0104/4",
+ "contents": "{{#subobject: |Has text=Text with a category|@category=Q0104}} {{#subobject: |Has text=Text without a category}}"
+ }
+ ],
+ "beforeTest": {
+ "job-run": [
+ "SMW\\SearchTableUpdateJob"
+ ]
+ },
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 with boolean include/not include",
+ "condition": "[[Has text::~+MariaDB -database]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0104/1#0##_55b020117d21e4b7967cf5bf78cf6b32"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has text::~+database]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0104/1#0##_7980f674d00e51fbc91cc663a43054c5",
+ "Example/Q0104/1#0##_507a001e2e9e0e7659aa33e8c4b2d471",
+ "Example/Q0104/1#0##_1a377960fd7e6c287e97c519278761b4"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (plus sorting)",
+ "condition": "[[Has text::~DATA*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_text": "DESC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0104/1#0##_1a377960fd7e6c287e97c519278761b4",
+ "Example/Q0104/1#0##_507a001e2e9e0e7659aa33e8c4b2d471",
+ "Example/Q0104/1#0##_7980f674d00e51fbc91cc663a43054c5"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (plus sorting)",
+ "condition": "[[Has text::~sear*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_text": "ASC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0104/2#0##_977ae79c0c362dc7a2ceaf94859178e7",
+ "Example/Q0104/2#0##_29a504fbd2492700363d5491902958e9"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 include/not include",
+ "condition": "[[Has text::~sear*, -elas*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_text": "DESC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0104/2#0##_29a504fbd2492700363d5491902958e9"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 same as #4",
+ "condition": "[[Has text::!~elastic*, +sear*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0104/2#0##_29a504fbd2492700363d5491902958e9"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 phrase matching",
+ "condition": "[[Has text::~\"phrase that has special\"]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0104/3#0##_1aa6fcbe946e44dc061627ce545e0cd9"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 similar to #5 but not used in phrase matching mode",
+ "condition": "[[Has text::~phrase that has special]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0104/3#0##_1aa6fcbe946e44dc061627ce545e0cd9",
+ "Example/Q0104/3#0##_682a8c9f798c14548a4599b68d83b78e"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8 free search (wide proximity)",
+ "skip-on": {
+ "sqlite": "works different in comparison to MySQL, see #9",
+ "elastic": "Uses a multi_field phrase match"
+ },
+ "condition": "[[~~with a category]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0104/4#0##_5a524a435267f6e6d2d45d64a419c1da",
+ "Example/Q0104/4#0##_9f7e6f010523ae7a6d1639d40773e379"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8.elastic free search (wide proximity)",
+ "skip-on": {
+ "elastic": [ "not", "Different behaviour as SQL on the exact phrase `with a category` " ]
+ },
+ "condition": "[[~~with a category]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0104/4#0##_9f7e6f010523ae7a6d1639d40773e379"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9 free search (wide proximity)",
+ "condition": "[[~~with* a category]] [[~Example/Q0104/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0104/4#0##_5a524a435267f6e6d2d45d64a419c1da",
+ "Example/Q0104/4#0##_9f7e6f010523ae7a6d1639d40773e379"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10 free search (wide proximity)",
+ "condition": "[[~~with a category]] [[Category:Q0104]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0104/4#0##_9f7e6f010523ae7a6d1639d40773e379"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#11 retain spaces on +/- operators",
+ "condition": "[[Has text::~+*maria* -postgres*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0104/1#0##_7980f674d00e51fbc91cc663a43054c5",
+ "Example/Q0104/1#0##_507a001e2e9e0e7659aa33e8c4b2d471",
+ "Example/Q0104/1#0##_55b020117d21e4b7967cf5bf78cf6b32"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEnabledFulltextSearch": true,
+ "smwgFulltextDeferredUpdate": false,
+ "smwgFulltextSearchIndexableDataTypes": [
+ "SMW_FT_BLOB",
+ "SMW_FT_URI"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "Fulltext not supported by PostgreSQL.",
+ "sesame": "Fulltext not supported by SPARQLStore (Sesame).",
+ "virtuoso": "Fulltext not supported by SPARQLStore (Virtuoso).",
+ "fuseki": "Fulltext not supported by SPARQLStore (Fuskei).",
+ "blazegraph": "Fulltext not supported by SPARQLStore (Blazegraph)."
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0105.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0105.json
new file mode 100644
index 00000000..ba946ead
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0105.json
@@ -0,0 +1,338 @@
+{
+ "description": "Test `_wpg`/`~` with enabled full-text search support (only enabled for MySQL, SQLite, `SMW_FT_WIKIPAGE`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/Q0105/1",
+ "contents": "{{#subobject: |Has page=MySQL vs MariaDB database}} {{#subobject: |Has page=Oracle vs MariaDB database}} {{#subobject: |Has page=PostgreSQL vs MariaDB database and more of}} {{#subobject: |Has page=MariaDB overview}}"
+ },
+ {
+ "page": "Example/Q0105/2",
+ "contents": "{{#subobject: |Has page=Elastic search}} {{#subobject: |Has page=Sphinx search}}"
+ },
+ {
+ "page": "Example/Q0105/3",
+ "contents": "{{#subobject: |Has page=...a hyphenated phrase that has special significance when it appears at the beginning of text...}} {{#subobject: |Has page=...a hyphenated phrase that has NOT any special significance when it appears at the beginning of text...}}"
+ },
+ {
+ "page": "Example/Q0105/4",
+ "contents": "{{#subobject: |Has page=Text with a category|@category=Q0105}} {{#subobject: |Has page=Text without a category}}"
+ }
+ ],
+ "beforeTest": {
+ "job-run": [
+ "SMW\\SearchTableUpdateJob"
+ ]
+ },
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 with boolean include/not include",
+ "condition": "[[Has page::~+MariaDB -database]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0105/1#0##_13bfd7da17ee73035f210b926e671c83"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has page::~+database]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0105/1#0##_d1e52a56041afb2795ebc6683f9a5229",
+ "Example/Q0105/1#0##_e64ad35fdcd8d9e99f2db9a815e36be3",
+ "Example/Q0105/1#0##_4b9aef2f903c80012ed4000b519a039d"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (plus sorting)",
+ "condition": "[[Has page::~DATA*]]",
+ "skip-on": {
+ "elastic": "ES, not expect a prefix search without an explicit wildcard (*)."
+ },
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_page": "DESC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0105/1#0##_d1e52a56041afb2795ebc6683f9a5229",
+ "Example/Q0105/1#0##_e64ad35fdcd8d9e99f2db9a815e36be3",
+ "Example/Q0105/1#0##_4b9aef2f903c80012ed4000b519a039d"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2.elastic (plus sorting)",
+ "condition": "[[Has page::~*DATA*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_page": "DESC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0105/1#0##_d1e52a56041afb2795ebc6683f9a5229",
+ "Example/Q0105/1#0##_e64ad35fdcd8d9e99f2db9a815e36be3",
+ "Example/Q0105/1#0##_4b9aef2f903c80012ed4000b519a039d"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (plus sorting)",
+ "condition": "[[Has page::~sear*]]",
+ "skip-on": {
+ "elastic": "ES, not expect a prefix search without an explicit wildcard (*)."
+ },
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_page": "ASC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0105/2#0##_4e8a7e81b361d0e14670809d9a1ff614",
+ "Example/Q0105/2#0##_7927dc49ee111e0929a91a1f357d9906"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3.elastic (plus sorting)",
+ "condition": "[[Has page::~*sear*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_page": "ASC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0105/2#0##_4e8a7e81b361d0e14670809d9a1ff614",
+ "Example/Q0105/2#0##_7927dc49ee111e0929a91a1f357d9906"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 include/not include",
+ "condition": "[[Has page::~sear*, -elas*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_page": "DESC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0105/2#0##_7927dc49ee111e0929a91a1f357d9906"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 same as #4",
+ "condition": "[[Has page::!~elastic*, +sear*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0105/2#0##_7927dc49ee111e0929a91a1f357d9906"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 phrase matching",
+ "condition": "[[Has page::~\"phrase that has special\"]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0105/3#0##_6b717d3124b3d294797a43ed5064374c"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 similar to #5 but not used in phrase matching mode",
+ "condition": "[[Has page::~phrase that has special]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0105/3#0##_6b717d3124b3d294797a43ed5064374c",
+ "Example/Q0105/3#0##_1dd972ef96528fe09e971c88ed933a7a"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8 free search (wide proximity)",
+ "skip-on": {
+ "elastic": "ES matches only `with` not `without`",
+ "sqlite": "works different in comparison to MySQL, see #9"
+ },
+ "condition": "[[~~with a category]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0105/4#0##_9f1222a5f6669be2c5f76dd5af08a4dc",
+ "Example/Q0105/4#0##_b827401b701c08c3c3d610a3a43d18c3"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8.elastic, free search (wide proximity, also match the annotated value)",
+ "skip-on": {
+ "elastic": [ "not", "See #8" ]
+ },
+ "condition": "[[~~with a category]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0105/4#0##_9f1222a5f6669be2c5f76dd5af08a4dc",
+ "Text_with_a_category#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9 free search (wide proximity)",
+ "condition": "[[~~with* a category]] [[~Example/Q0105/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0105/4#0##_9f1222a5f6669be2c5f76dd5af08a4dc",
+ "Example/Q0105/4#0##_b827401b701c08c3c3d610a3a43d18c3"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10 free search (wide proximity)",
+ "condition": "[[~~with a category]] [[Category:Q0105]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0105/4#0##_9f1222a5f6669be2c5f76dd5af08a4dc"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#11 retain spaces on +/- operators",
+ "condition": "[[Has page::~+*maria* -postgres*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0105/1#0##_d1e52a56041afb2795ebc6683f9a5229",
+ "Example/Q0105/1#0##_e64ad35fdcd8d9e99f2db9a815e36be3",
+ "Example/Q0105/1#0##_13bfd7da17ee73035f210b926e671c83"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#12 same as #11 only with `,` (required by MySQL 5.7/MariaDB 10.1)",
+ "condition": "[[Has page::~+*maria*, -postgres*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0105/1#0##_d1e52a56041afb2795ebc6683f9a5229",
+ "Example/Q0105/1#0##_e64ad35fdcd8d9e99f2db9a815e36be3",
+ "Example/Q0105/1#0##_13bfd7da17ee73035f210b926e671c83"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEnabledFulltextSearch": true,
+ "smwgFulltextDeferredUpdate": false,
+ "smwgFulltextSearchIndexableDataTypes": [
+ "SMW_FT_BLOB",
+ "SMW_FT_URI",
+ "SMW_FT_WIKIPAGE"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "Fulltext not supported by PostgreSQL.",
+ "sesame": "Fulltext not supported by SPARQLStore (Sesame).",
+ "virtuoso": "Fulltext not supported by SPARQLStore (Virtuoso).",
+ "fuseki": "Fulltext not supported by SPARQLStore (Fuskei).",
+ "blazegraph": "Fulltext not supported by SPARQLStore (Blazegraph)."
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json
new file mode 100644
index 00000000..6e5a65ab
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0106.json
@@ -0,0 +1,94 @@
+{
+ "description": "Test `_txt`/`~` with enabled full-text search support on fixed user property (only enabled for MySQL, SQLite, `smwgFixedProperties`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has fixed text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has fixed page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/Q0106/1",
+ "contents": "{{#subobject: |Has fixed text=MySQL vs MariaDB database}} {{#subobject: |Has fixed text=Oracle vs MariaDB database}} {{#subobject: |Has fixed text=PostgreSQL vs MariaDB database and more of}} {{#subobject: |Has fixed text=MariaDB overview}}"
+ },
+ {
+ "page": "Example/Q0106/2",
+ "contents": "{{#subobject: |Has fixed page=Elastic search}} {{#subobject: |Has fixed page=Sphinx search}}"
+ }
+ ],
+ "beforeTest": {
+ "maintenance-run": {
+ "rebuildData": {
+ "page": "Property:Has fixed text|Property:Has fixed page|Example/Q0106/1|Example/Q0106/2"
+ }
+ }
+ },
+ "tests": [
+ {
+ "type": "query",
+ "store": {
+ "clear-cache": true
+ },
+ "about": "#0 on fixed blob user property",
+ "condition": "[[Has fixed text::~+MariaDB -database]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0106/1#0##_29f6aa337d1dc1e2f79376c7940aeab3"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "store": {
+ "clear-cache": true
+ },
+ "about": "#1 on fixed page user property",
+ "condition": "[[Has fixed page::~*search*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0106/2#0##_39c07b506d692088c97dc0d1cbfd67e6",
+ "Example/Q0106/2#0##_89e5e037d244e08b050101bb8ddb7768"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEnabledFulltextSearch": true,
+ "smwgFulltextDeferredUpdate": false,
+ "smwgFulltextSearchIndexableDataTypes": [
+ "SMW_FT_BLOB",
+ "SMW_FT_URI",
+ "SMW_FT_WIKIPAGE"
+ ],
+ "smwgFixedProperties": [
+ "Has_fixed_text",
+ "Has fixed page"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "Fulltext not supported by PostgreSQL.",
+ "sesame": "Fulltext not supported by SPARQLStore (Sesame).",
+ "virtuoso": "Fulltext not supported by SPARQLStore (Virtuoso).",
+ "fuseki": "Fulltext not supported by SPARQLStore (Fuskei).",
+ "blazegraph": "Fulltext not supported by SPARQLStore (Blazegraph)."
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0201.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0201.json
new file mode 100644
index 00000000..a1d404ee
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0201.json
@@ -0,0 +1,130 @@
+{
+ "description": "Test `_CONC` queries (skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Population",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has concept description",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Page one",
+ "contents": "[[Population::1001]], [[Has concept description::Bar]]"
+ },
+ {
+ "page": "Page two",
+ "contents": "[[Has concept description::Foo]], [[Population::9999]]"
+ },
+ {
+ "page": "Page three",
+ "contents": "[[Has concept description::Bar]]"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept for any value selection",
+ "contents": "{{#concept: [[Population::+]][[Has concept description::+]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept for any broader value selection",
+ "contents": "{{#concept: [[Has concept description::+]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept for distinct value selection",
+ "contents": "{{#concept: [[Has concept description::Foo]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Composite concept for a conjunctive condition",
+ "contents": "{{#concept: [[Concept:Concept for any value selection]][[Concept:Concept for distinct value selection]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Composite concept for a disjunctive condition",
+ "contents": "{{#concept: [[Concept:Concept for any value selection]] OR [[Concept:Concept for distinct value selection]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "concept",
+ "about": "#0 Simple concept member list",
+ "condition": "[[Concept:Concept for any value selection]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2"
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept for any value selection",
+ "count": "2"
+ }
+ ]
+ },
+ {
+ "type": "concept",
+ "about": "#1 Simple concept distinct member list",
+ "condition": "[[Concept:Concept for distinct value selection]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1"
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept for distinct value selection",
+ "count": "1"
+ }
+ ]
+ },
+ {
+ "type": "concept",
+ "about": "#2 Composite concept set by conjunctive conditions",
+ "condition": "[[Concept:Composite concept for a conjunctive condition]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1"
+ },
+ "conceptcache": [
+ {
+ "concept": "Composite concept for a conjunctive condition",
+ "count": "1"
+ }
+ ]
+ },
+ {
+ "type": "concept",
+ "about": "#3 Composite concept set by disjunctive conditions",
+ "condition": "[[Concept:Composite concept for a disjunctive condition]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2"
+ },
+ "conceptcache": [
+ {
+ "concept": "Composite concept for a disjunctive condition",
+ "count": "2"
+ }
+ ]
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso reports 'SPARQL compiler: Blank node ... is not allowed in a constant clause', see https://github.com/openlink/virtuoso-opensource/issues/126"
+ },
+ "version": "2",
+ "is-incomplete": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0202.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0202.json
new file mode 100644
index 00000000..101e4ea7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0202.json
@@ -0,0 +1,123 @@
+{
+ "description": "Test `_CONC` for guarding against circular/self-reference which otherwise would fail with 'Maximum function nesting level ... reached, aborting' (#945, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has concept description",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Page one",
+ "contents": "[[Has concept description::Bar]]"
+ },
+ {
+ "page": "Page two",
+ "contents": "[[Has concept description::Foo]]"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept-is-not-circular",
+ "contents": "{{#concept: [[Has concept description::+]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept-is-circular",
+ "contents": "{{#concept: [[Concept:Concept-is-circular]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept-is-circular-extra",
+ "contents": "{{#concept: [[Has concept description::+]] [[Concept:Concept-is-circular-extra]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept-is-circular-extra-extra",
+ "contents": "{{#concept: [[Has concept description::+]] [[Has concept description::+]] OR [[Concept:Concept-is-circular-extra]] [[Concept:Concept-is-circular]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "concept",
+ "about": "#0 Check simple concept list",
+ "condition": "[[Concept:Concept-is-not-circular]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2"
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept-is-not-circular",
+ "count": "2"
+ }
+ ]
+ },
+ {
+ "type": "concept",
+ "about": "#1 Check for circular concept",
+ "condition": "[[Concept:Concept-is-circular]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "error": ">1"
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept-is-circular",
+ "count": null
+ }
+ ]
+ },
+ {
+ "type": "concept",
+ "about": "#2 Check for circular concept (conjunction)",
+ "condition": "[[Concept:Concept-is-circular-extra]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "error": ">1"
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept-is-circular-extra",
+ "count": null
+ }
+ ]
+ },
+ {
+ "type": "concept",
+ "about": "#3 Check for circular concept (disjunctions)",
+ "condition": "[[Concept:Concept-is-circular-extra-extra]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "error": ">1"
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept-is-circular-extra-extra",
+ "count": 2
+ }
+ ]
+ }
+ ],
+ "settings": {
+ "smwgQueryResultCacheType": false,
+ "smwgQFilterDuplicates": false,
+ "smwgQConceptCaching": "CONCEPT_CACHE_NONE"
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso reports 'SPARQL compiler: Blank node ... is not allowed in a constant clause', see https://github.com/openlink/virtuoso-opensource/issues/126"
+ },
+ "version": "2",
+ "is-incomplete": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0203.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0203.json
new file mode 100644
index 00000000..a046c4fb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0203.json
@@ -0,0 +1,71 @@
+{
+ "description": "Test `_CONC` to use `CONCEPT_CACHE_ALL` (#1050, skip all SPARQL repository)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has description",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Page-one",
+ "contents": "[[Has description::Bar]] [[Category:Q0203]]"
+ },
+ {
+ "page": "Page-two",
+ "contents": "[[Has description::Foo]] [[Category:Q0203]]"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept-for-any-description",
+ "contents": "{{#concept: [[Has description::+]] [[Category:Q0203]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 any value with CONCEPT_CACHE_ALL set (wiki configuration requires the cache to be computed off-line)",
+ "condition": "[[Concept:Concept-for-any-description]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "error": 1
+ }
+ },
+ {
+ "type": "concept",
+ "about": "#1 Check cache",
+ "condition": "[[Concept:Concept-for-any-description]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "error": 1
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept-for-any-description",
+ "count": 2
+ }
+ ]
+ }
+ ],
+ "settings": {
+ "smwgQConceptCaching": "CONCEPT_CACHE_ALL"
+ },
+ "meta": {
+ "skip-on": {
+ "elastic": "CONCEPT_CACHE_ALL isn't implemented",
+ "virtuoso": "CONCEPT_CACHE_ALL isn't implemented",
+ "sesame": "CONCEPT_CACHE_ALL isn't implemented",
+ "fuseki": "CONCEPT_CACHE_ALL isn't implemented",
+ "blazegraph": "CONCEPT_CACHE_ALL isn't implemented"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0204.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0204.json
new file mode 100644
index 00000000..0c2d4dd3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0204.json
@@ -0,0 +1,109 @@
+{
+ "description": "Test `_CONC` on predefined inverse query and subobject inverse query (#1096, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Page/02/04-1",
+ "contents": "{{#subobject:|Has page=Page/02/04-1}}"
+ },
+ {
+ "page": "Page/02/04-2",
+ "contents": "[[Has page::Page/02/04-2]]"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept-for-inverse-pre-defined-property",
+ "contents": "{{#concept: [[-Has page.-Has subobject::Page/02/04-1]] }}"
+ },
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "Concept-for-inverse-user-defined-property",
+ "contents": "{{#concept: [[-Has page.-Has page::Page/02/04-2]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 inverse for pre-defined property",
+ "condition": "[[-Has page.-Has subobject::Page/02/04-1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page/02/04-1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 inverse for user-defined-property",
+ "condition": "[[-Has page.-Has page::Page/02/04-2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page/02/04-2#0##"
+ ]
+ }
+ },
+ {
+ "type": "concept",
+ "about": "#2",
+ "condition": "[[Concept:Concept-for-inverse-pre-defined-property]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page/02/04-1#0##"
+ ]
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept-for-inverse-pre-defined-property",
+ "count": 1
+ }
+ ]
+ },
+ {
+ "type": "concept",
+ "about": "#3",
+ "condition": "[[Concept:Concept-for-inverse-user-defined-property]]",
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page/02/04-2#0##"
+ ]
+ },
+ "conceptcache": [
+ {
+ "concept": "Concept-for-inverse-user-defined-property",
+ "count": 1
+ }
+ ]
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso reports 'SPARQL compiler: Blank node ... is not allowed in a constant clause', see https://github.com/openlink/virtuoso-opensource/issues/126"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0301.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0301.json
new file mode 100644
index 00000000..0e09d46d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0301.json
@@ -0,0 +1,134 @@
+{
+ "description": "Test `_IMPO` queries for imported foaf vocabulary (#891, en)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import foaf",
+ "contents": "http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name|Type:Text\n homepage|Type:URL\n mbox|Type:Email\n mbox_sha1sum|Type:Text\n depiction|Type:URL\n phone|Type:Text\n Person|Category\n Organization|Category\n knows|Type:Page\n member|Type:Page\n"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:homepage",
+ "contents": "[[Imported from::foaf:homepage]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:name",
+ "contents": "[[Imported from::foaf:name]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:knows",
+ "contents": "[[Imported from::foaf:knows]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has name",
+ "contents": "#REDIRECT [[Property:Foaf:name]]"
+ },
+ {
+ "page": "John Doe",
+ "contents": "[[Foaf:name::John Doe]], [[Foaf:homepage::http://example.org/JohnDoe]] [[Foaf:knows::Jane Doe]]"
+ },
+ {
+ "page": "Jane Doe",
+ "contents": "[[Foaf:name::Jane Doe]], [[Foaf:homepage::http://example.org/JaneDoe]] [[Foaf:knows::John Doe]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Foaf:name::John Doe]] OR [[Foaf:name::Jane Doe]]",
+ "printouts": [
+ "Foaf:name",
+ "Foaf:knows"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "John Doe#0##",
+ "Jane Doe#0##"
+ ],
+ "count": "2",
+ "datavalues": [
+ {
+ "property": "Foaf:name",
+ "value": "John Doe"
+ },
+ {
+ "property": "Foaf:name",
+ "value": "Jane Doe"
+ },
+ {
+ "property": "Foaf:knows",
+ "value": "Jane Doe"
+ },
+ {
+ "property": "Foaf:knows",
+ "value": "John Doe"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 check auto-property types, #891",
+ "condition": "[[Foaf:name::John Doe]] OR [[Foaf:name::Jane Doe]]",
+ "printouts": [
+ "Foaf:homepage"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "John Doe#0##",
+ "Jane Doe#0##"
+ ],
+ "count": "2",
+ "dataitems": [
+ {
+ "type": "_uri",
+ "value": "http://example.org/JohnDoe"
+ },
+ {
+ "type": "_uri",
+ "value": "http://example.org/JaneDoe"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 query on redirected property",
+ "condition": "[[Has name::John Doe]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "John Doe#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0401.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0401.json
new file mode 100644
index 00000000..30096e72
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0401.json
@@ -0,0 +1,163 @@
+{
+ "description": "Test `_SUBP` on a simple 'family' subproperty hierarchy example query (#1003, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Family (http://www.cs.man.ac.uk/~stevensr/ontology/family.rdf.owl)",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Spouse",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has wife",
+ "contents": "[[Has type::Page]] [[Subproperty of::Spouse]] [[Subproperty of::Family]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has husband",
+ "contents": "[[Has type::Page]] [[Subproperty of::Spouse]] [[Subproperty of::Family]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has child",
+ "contents": "[[Has type::Page]] [[Subproperty of::Family]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has brother",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has sister",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "John Doe",
+ "contents": "[[Has wife::Jane Doe]] [[Has child::Jonnie Doe]] [[Has child::Janie Doe]]"
+ },
+ {
+ "page": "Jane Doe",
+ "contents": "[[Has husband::John Doe]]"
+ },
+ {
+ "page": "Jonnie Doe",
+ "contents": "[[Has sister::Janie Doe]]"
+ },
+ {
+ "page": "Janie Doe",
+ "contents": "[[Has brother::Jonnie Doe]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 Spouse to search any value",
+ "condition": "[[Spouse::+]]",
+ "printouts": [
+ "Has wife",
+ "Has husband"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "John Doe#0##",
+ "Jane Doe#0##"
+ ],
+ "count": "2",
+ "datavalues": [
+ {
+ "property": "Has wife",
+ "value": "Jane Doe"
+ },
+ {
+ "property": "Has husband",
+ "value": "John Doe"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 Disjunctive query for distinct spouse value",
+ "condition": "[[Spouse::John Doe]] OR [[Spouse::Jane Doe]]",
+ "printouts": [
+ "Has wife",
+ "Has husband"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "John Doe#0##",
+ "Jane Doe#0##"
+ ],
+ "count": "2",
+ "datavalues": [
+ {
+ "property": "Has wife",
+ "value": "Jane Doe"
+ },
+ {
+ "property": "Has husband",
+ "value": "John Doe"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 find members of a super property",
+ "condition": "[[Subproperty of::Property:Spouse]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Has wife#102##",
+ "Has husband#102##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 find the super properties (invert)",
+ "condition": "[[-Subproperty of::Property:Has wife]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Spouse#102##",
+ "Family#102##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgQSubpropertyDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/property hierarchies are currently not implemented"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0402.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0402.json
new file mode 100644
index 00000000..31137378
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0402.json
@@ -0,0 +1,248 @@
+{
+ "description": "Test `_SUBP` to map DC imported vocabulary with MARC 21 bibliographic terms (#1003, http://www.loc.gov/marc/bibliographic/bd20x24x.html)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import dc",
+ "contents": "http://purl.org/dc/elements/1.1/|[http://purl.org/dc/elements/1.1/ dc]\n title|Type:Text\n type|Type:Text\n date|Type:Date\n description|Type:Text\n creator|Type:Page\n"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Dc:title",
+ "contents": "[[Imported from::dc:title]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Dc:creator",
+ "contents": "[[Imported from::dc:creator]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Marc:title",
+ "contents": "[[Has type::Text]] [[Subproperty of::Dc:title]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Marc:main entry personal name",
+ "contents": "[[Has type::Page]] [[Subproperty of::Dc:creator]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Marc:title statement",
+ "contents": "[[Has type::Text]] [[Subproperty of::Marc:title]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Marc:varying form of title",
+ "contents": "[[Has type::Text]] [[Subproperty of::Marc:title]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has author",
+ "contents": "#REDIRECT [[Property:Marc:main entry personal name]]"
+ },
+ {
+ "page": "Animal farm",
+ "contents": "[[Marc:title statement::George Orwell's Animal farm]] [[Has author::George Orwell]]"
+ },
+ {
+ "page": "War and Peace",
+ "contents": "[[Marc:title statement::War and Peace]] [[Has author::Leo Tolstoy]]"
+ },
+ {
+ "page": "King Lear",
+ "contents": "#REDIRECT [[Shakespeare's King Lear]]"
+ },
+ {
+ "page": "Shakespeare",
+ "contents": "#REDIRECT [[William Shakespeare]]"
+ },
+ {
+ "page": "Shakespeare's King Lear",
+ "contents": "[[Marc:title::King Lear]] [[Has author::William Shakespeare]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 any value for Marc:title statement",
+ "condition": "[[Marc:title statement::+]]",
+ "printouts": [
+ "Has author"
+ ],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Animal farm#0##",
+ "War and Peace#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has author",
+ "value": "Leo Tolstoy"
+ },
+ {
+ "property": "Has author",
+ "value": "George Orwell"
+ }
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 any value for Marc:title on level one of the subproperty hierarchy",
+ "condition": "[[Marc:title::+]]",
+ "printouts": [
+ "Has author"
+ ],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Animal farm#0##",
+ "War and Peace#0##",
+ "Shakespeare's King Lear#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has author",
+ "value": "Leo Tolstoy"
+ },
+ {
+ "property": "Has author",
+ "value": "George Orwell"
+ },
+ {
+ "property": "Has author",
+ "value": "William Shakespeare"
+ }
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 any value for Dc:title on level two of the subproperty hierarchy",
+ "condition": "[[Dc:title::+]]",
+ "printouts": [
+ "Has author"
+ ],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Animal farm#0##",
+ "War and Peace#0##",
+ "Shakespeare's King Lear#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has author",
+ "value": "Leo Tolstoy"
+ },
+ {
+ "property": "Has author",
+ "value": "George Orwell"
+ },
+ {
+ "property": "Has author",
+ "value": "William Shakespeare"
+ }
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 distinct value for Dc:title on level two of the subproperty hierarchy",
+ "condition": "[[Dc:title::~*Animal*]]",
+ "printouts": [
+ "Has author"
+ ],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Animal farm#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has author",
+ "value": "George Orwell"
+ }
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 distinct value for Has author / redirected value / subproperty level zero",
+ "condition": "[[Has author::Shakespeare]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Shakespeare's King Lear#0##"
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 distinct value for Dc:creator / redirected value / subproperty level one",
+ "condition": "[[Dc:creator::Shakespeare]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Shakespeare's King Lear#0##"
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ }
+ ],
+ "settings": {
+ "smwgQSubpropertyDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_REDI",
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/property hierarchies are currently not implemented"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0501.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0501.json
new file mode 100644
index 00000000..a0535128
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0501.json
@@ -0,0 +1,130 @@
+{
+ "description": "Test `_qty` queries for custom unit (km²/°C) property value assignments",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Area",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]][[Corresponds to::1000 m²]][[Corresponds to::0.38610 sq mi]][[Corresponds to::247.1054 acre]][[Corresponds to::988.4215 rood]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has average high temperature",
+ "contents": "[[Has type::Temperature]]"
+ },
+ {
+ "page": "Berlin",
+ "contents": "[[Area::891.85 km²]], [[Has average high temperature::13.4 °C]]"
+ },
+ {
+ "page": "Paris",
+ "contents": "[[Area::105.40 km²]], [[Has average high temperature::16.0 °C]]"
+ },
+ {
+ "page": "æ±äº¬éƒ½",
+ "contents": "[[Area::845 sq mi]], [[Has average high temperature::26.0 °C]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 Wildcard search for any value",
+ "condition": "[[Area::+]]",
+ "printouts": [
+ "Area"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Berlin#0##",
+ "Paris#0##",
+ "æ±äº¬éƒ½#0##"
+ ],
+ "count": "3",
+ "datavalues": [
+ {
+ "property": "Area",
+ "value": "891.85 km²"
+ },
+ {
+ "property": "Area",
+ "value": "105.40 km²"
+ },
+ {
+ "property": "Area",
+ "value": "845 sq mi"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 Search for distinct value",
+ "condition": "[[Area::891.85]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Berlin#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 Search for less than distinct value",
+ "condition": "[[Has average high temperature::<15.0 °C]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Berlin#0##"
+ ],
+ "count": "1"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 Search for greater than or equal distinct value",
+ "condition": "[[Has average high temperature::≥16.0 °C]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Paris#0##",
+ "æ±äº¬éƒ½#0##"
+ ],
+ "count": "2"
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 Search for greater than distinct value",
+ "condition": "[[Has average high temperature::>70 °F]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "æ±äº¬éƒ½#0##"
+ ],
+ "count": "1"
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "version": "2",
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0502.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0502.json
new file mode 100644
index 00000000..65bf2844
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0502.json
@@ -0,0 +1,84 @@
+{
+ "description": "Test `_qty` range queries using non strict comparators (`smwStrictComparators=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has starting wattage",
+ "contents": "[[Has type::Quantity]] [[Display units::kW]] [[Corresponds to::1 W, Watt, Watts]] [[Corresponds to::0.001 kW]] [[Corresponds to::0.0013410220 hp, bhp, horsepower]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has running wattage",
+ "contents": "[[Has type::Quantity]] [[Display units::kW]] [[Corresponds to::1 W, Watt, Watts]] [[Corresponds to::0.001 kW]] [[Corresponds to::0.0013410220 hp, bhp, horsepower]]"
+ },
+ {
+ "page": "Home appliance",
+ "contents": "{{#subobject:MicrowaveOven|Has starting wattage=1 kW|Has running wattage=1 kW}} {{#subobject:Refrigerator|Has starting wattage=1.2 kW|Has running wattage=130 W}} {{#subobject:Dishwasher|Has starting wattage=540 W|Has running wattage=200 W}} {{#subobject:Blender|Has starting wattage=840 W|Has running wattage=400 W}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has starting wattage::≥1 kW]]",
+ "printouts": [
+ "Has starting wattage"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Home appliance#0##MicrowaveOven",
+ "Home appliance#0##Refrigerator"
+ ],
+ "count": "2",
+ "datavalues": [
+ {
+ "property": "Has starting wattage",
+ "value": "1.2 kW"
+ },
+ {
+ "property": "Has starting wattage",
+ "value": "1 kW"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 Conjunctive condition",
+ "condition": "[[Has starting wattage::≥1 kW]] [[Has running wattage::< 500 W]]",
+ "printouts": [
+ "Has starting wattage",
+ "Has running wattage"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Home appliance#0##Refrigerator"
+ ],
+ "count": "1",
+ "datavalues": [
+ {
+ "property": "Has starting wattage",
+ "value": "1.2 kW"
+ },
+ {
+ "property": "Has running wattage",
+ "value": "130 W"
+ }
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "version": "2",
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0503.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0503.json
new file mode 100644
index 00000000..ff650628
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0503.json
@@ -0,0 +1,87 @@
+{
+ "description": "Test `_qty` on positional unit preference in query condition (#1329, `smwStrictComparators=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Currency",
+ "contents": "[[Has type::Quantity]], [[Display units::€,£,¥]] [[Corresponds to::€ 1]] [[Corresponds to::1.06 US, US$, $]] [[Corresponds to::0.70 British Pound,GBP,£]] [[Corresponds to::¥,JPY,Japanese Yen 114.2121]]"
+ },
+ {
+ "page": "Example/Q0503/1",
+ "contents": "[[Currency::12 €]] [[Currency::¥ 500]] [[Currency::2 £]]"
+ },
+ {
+ "page": "Example/Q0503/2",
+ "contents": "[[Currency::€ 20]] [[Currency::2000 JPY]] [[Currency::0.5 GBP]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Currency::€ 20]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0503/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Currency::<Â¥300]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0503/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Currency::≥1400 JPY]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0503/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Currency::< € .8]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0503/2#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "version": "2",
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0601.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0601.json
new file mode 100644
index 00000000..b66d2809
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0601.json
@@ -0,0 +1,77 @@
+{
+ "description": "Test `_wpg` for property chain query queries",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Located in",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Member of",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Europe",
+ "contents": "[[Member of::European Union]] {{#subobject:Member of=NATO}}"
+ },
+ {
+ "page": "France",
+ "contents": "[[Located in::Europe]]"
+ },
+ {
+ "page": "Germany",
+ "contents": "{{#set:Located in=Europe}}"
+ },
+ {
+ "page": "Italy",
+ "contents": "{{#subobject:Located in=Europe}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Located in.Member of::European Union]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "3",
+ "results": [
+ "Germany#0##",
+ "France#0##",
+ "Italy#0##_261bcb222bdef3105c6906115585880c"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Located in.Has subobject.Member of::NATO]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "3",
+ "results": [
+ "Germany#0##",
+ "France#0##",
+ "Italy#0##_261bcb222bdef3105c6906115585880c"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0602.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0602.json
new file mode 100644
index 00000000..7136cf26
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0602.json
@@ -0,0 +1,48 @@
+{
+ "description": "Test `_wpg` sort query with #subobject annotated @sortkey content",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Member of",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Page-with-subobject",
+ "contents": "{{#subobject:|Member of=WXYZ|@sortkey=B}}\n {{#subobject:|Member of=ABCD|@sortkey=A}}\n {{#subobject:|Member of=ABCD|@sortkey=A}}\n {{#subobject:|Member of=ABCD|@sortkey=C}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Member of::+]]",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Member_of": "DESC"
+ }
+ },
+ "assert-queryresult": {
+ "count": "3",
+ "results": [
+ "Page-with-subobject#0##_7aa07758037723bb0d3522a1a151771f",
+ "Page-with-subobject#0##_cd630d70e4e469611f361bcda9cf919a",
+ "Page-with-subobject#0##_38a501d710af2a3167121d6282e64fe6"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0603.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0603.json
new file mode 100644
index 00000000..eba878e9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0603.json
@@ -0,0 +1,230 @@
+{
+ "description": "Test `_wpg` queries for various conditions using #set annotated content",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Member of",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Page-with-set-1",
+ "contents": "{{#set:|Member of=Foo}}\n {{#set:|Member of=Bar}}"
+ },
+ {
+ "page": "Page-with-set-2",
+ "contents": "{{#set:|Member of=Foobaz}} {{#set:|Member of=Bar}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Member of::Foo]]",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-set-1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Member of",
+ "value": "Foo"
+ },
+ {
+ "property": "Member of",
+ "value": "Bar"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Member of::~*Foo*]]",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2",
+ "results": [
+ "Page-with-set-1#0##",
+ "Page-with-set-2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Member of",
+ "value": "Foo"
+ },
+ {
+ "property": "Member of",
+ "value": "Bar"
+ },
+ {
+ "property": "Member of",
+ "value": "Foobaz"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Member of::Foo]] OR [[Member of::Foobaz]]",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2",
+ "results": [
+ "Page-with-set-1#0##",
+ "Page-with-set-2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Member of",
+ "value": "Foo"
+ },
+ {
+ "property": "Member of",
+ "value": "Bar"
+ },
+ {
+ "property": "Member of",
+ "value": "Foobaz"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Member of::Foo||Foobaz]]",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2",
+ "results": [
+ "Page-with-set-1#0##",
+ "Page-with-set-2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Member of",
+ "value": "Foo"
+ },
+ {
+ "property": "Member of",
+ "value": "Bar"
+ },
+ {
+ "property": "Member of",
+ "value": "Foobaz"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Member of::Foobaz]] AND [[Member of::Bar]]",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-set-2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Member of",
+ "value": "Bar"
+ },
+ {
+ "property": "Member of",
+ "value": "Foobaz"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[Member of::Foobaz]] AND <q>[[Member of::Bar]] AND [[Member of::Foobaz]]</q>",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-set-2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Member of",
+ "value": "Bar"
+ },
+ {
+ "property": "Member of",
+ "value": "Foobaz"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6",
+ "condition": "[[Member of::Foobaz]] AND <q>[[Member of::Bar]] AND <q>[[Member of::Bar]] OR [[Member of::Foobaz]]</q></q>",
+ "printouts": [
+ "Member of"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-set-2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Member of",
+ "value": "Bar"
+ },
+ {
+ "property": "Member of",
+ "value": "Foobaz"
+ }
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0604.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0604.json
new file mode 100644
index 00000000..c2ffd25a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0604.json
@@ -0,0 +1,192 @@
+{
+ "description": "Test `_wpg` queries to resolve property/values redirects (#467, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has firstPage",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has secondPage",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "PropertyToBeRedirected",
+ "contents": "#REDIRECT [[Property:Has firstPage]]"
+ },
+ {
+ "page": "PageValueToBeRedirected",
+ "contents": "#REDIRECT [[PageRedirectTarget]]"
+ },
+ {
+ "page": "AnotherPageValueToBeRedirected",
+ "contents": "#REDIRECT [[AnotherPageRedirectTarget]]"
+ },
+ {
+ "page": "Page-one",
+ "contents": "[[PropertyToBeRedirected::One]]"
+ },
+ {
+ "page": "Page-two",
+ "contents": "{{#subobject:PropertyToBeRedirected=Two}}"
+ },
+ {
+ "page": "Page-three",
+ "contents": "[[Has secondPage::PageValueToBeRedirected]]"
+ },
+ {
+ "page": "Page-four",
+ "contents": "{{#subobject:Has secondPage=PageValueToBeRedirected}}"
+ },
+ {
+ "page": "Page-five-combined",
+ "contents": "[[PropertyToBeRedirected::PageValueToBeRedirected]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 any value query for redirected property",
+ "condition": "[[PropertyToBeRedirected::+]]",
+ "printouts": [
+ "PropertyToBeRedirected",
+ "Has firstPage"
+ ],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Page-one#0##",
+ "Page-two#0##_b60804b67d37b781ac15c6e78102d13c",
+ "Page-five-combined#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "PropertyToBeRedirected",
+ "value": "One"
+ },
+ {
+ "property": "PropertyToBeRedirected",
+ "value": "Two"
+ },
+ {
+ "property": "PropertyToBeRedirected",
+ "value": "PageValueToBeRedirected"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 any value query for redirected value",
+ "condition": "[[Has secondPage::+]]",
+ "printouts": [
+ "Has secondPage"
+ ],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Page-three#0##",
+ "Page-four#0##_f5bb3e35482aaa5d1eef24749c24af30"
+ ],
+ "datavalues": [
+ {
+ "property": "Has secondPage",
+ "value": "PageValueToBeRedirected"
+ },
+ {
+ "property": "Has secondPage",
+ "value": "PageValueToBeRedirected"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 disjunction query on discrete value search",
+ "condition": "[[PropertyToBeRedirected::One]] OR [[PropertyToBeRedirected::Two]] OR [[Has secondPage::PageValueToBeRedirected]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Page-one#0##",
+ "Page-two#0##_b60804b67d37b781ac15c6e78102d13c",
+ "Page-three#0##",
+ "Page-four#0##_f5bb3e35482aaa5d1eef24749c24af30"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 combined property/value redirect discrete value search",
+ "condition": "[[PropertyToBeRedirected::PageValueToBeRedirected]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page-five-combined#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 single value search, refs #1007",
+ "condition": "[[:PageValueToBeRedirected]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "PageRedirectTarget#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 disjunctive single value search, refs #1007",
+ "condition": "[[:PageValueToBeRedirected]] OR [[:AnotherPageValueToBeRedirected]] OR [[:Page-one]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "PageRedirectTarget#0##",
+ "AnotherPageRedirectTarget#0##",
+ "Page-one#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_REDI",
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not support property paths / SPARQL compiler, line 0: Invalid character in SPARQL expression at '^'"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0605.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0605.json
new file mode 100644
index 00000000..5a73a9e0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0605.json
@@ -0,0 +1,141 @@
+{
+ "description": "Test `_wpg` regex search (`!~/~*/~?`) queries (#679)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has regexpage",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Page-1-with-spaces",
+ "contents": "[[Has regexpage::Annotation test with spaces]]"
+ },
+ {
+ "page": "Page-2-with-spaces",
+ "contents": "[[Has regexpage::Annotation text with spaces]]"
+ },
+ {
+ "page": "Page-3-without-spaces",
+ "contents": "[[Has regexpage::AnnotationTestWithoutSpaces]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has regexpage::~Annotation te*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Page-1-with-spaces#0##",
+ "Page-2-with-spaces#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has regexpage::~Annotation tes*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page-1-with-spaces#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Has regexpage::~An??tation*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Page-1-with-spaces#0##",
+ "Page-2-with-spaces#0##",
+ "Page-3-without-spaces#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Has regexpage::~Annotation*]] [[Has regexpage::!~Annotation tex*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Page-1-with-spaces#0##",
+ "Page-3-without-spaces#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Has regexpage::~Annotation tes*]] OR [[Has regexpage::~Annotation tex*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Page-1-with-spaces#0##",
+ "Page-2-with-spaces#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[Has regexpage::~Annotation te?t with spaces]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Page-1-with-spaces#0##",
+ "Page-2-with-spaces#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6",
+ "condition": "[[Has regexpage::+]][[Has regexpage::!~Annotation te?t with spaces]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page-3-without-spaces#0##"
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0606.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0606.json
new file mode 100644
index 00000000..2887e384
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0606.json
@@ -0,0 +1,249 @@
+{
+ "description": "Test `_wpg`/`_num`/`_txt` using subqueries (#466, #627, #625)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Located in",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Member of",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has arbitrary number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has arbitrary text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]] [[Corresponds to::1000 m²]]"
+ },
+ {
+ "page": "City-A",
+ "contents": "[[Located in::Country-A]] {{#subobject:|Has arbitrary number=42|Has arbitrary text=abc}}"
+ },
+ {
+ "page": "City-B",
+ "contents": "[[Located in::Country-B]] {{#subobject:|Has arbitrary number=1001|Has arbitrary text=def}}"
+ },
+ {
+ "page": "City-C",
+ "contents": "[[Located in::Country-C]] {{#subobject:|Has area=891.85 km ²}}"
+ },
+ {
+ "page": "Country-A",
+ "contents": "[[Member of::EconomicUnion-A]] {{#subobject:|Member of=DefenseUnion-A}}"
+ },
+ {
+ "page": "Country-B",
+ "contents": "{{#subobject:|Member of=EconomicUnion-B}}"
+ },
+ {
+ "page": "EconomicUnion-A",
+ "contents": "[[Is part of::Community-A]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 as property chain notation",
+ "condition": "[[Located in.Member of::EconomicUnion-A]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "City-A#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 same as #0 as subquery notation",
+ "condition": "[[Located in::<q>[[Member of::EconomicUnion-A]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "City-A#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Located in.Member of.Is part of::Community-A]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "City-A#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Has subobject.Member of::EconomicUnion-B]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Country-B#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 SubqueryForCombinedSubobjectPropertyChain",
+ "condition": "[[Located in.Has subobject.Member of::EconomicUnion-B]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "City-B#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 SubqueryForCombinedSubobjectPropertyChainForWilcardSearch",
+ "condition": "[[Located in.Has subobject.Member of::+]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "City-A#0##",
+ "City-B#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 regex search",
+ "condition": "[[Has subobject.Member of::~*Union*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Country-A#0##",
+ "Country-B#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 wildcard search",
+ "condition": "[[Has subobject.Member of::+]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Country-A#0##",
+ "Country-B#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8",
+ "condition": "[[Located in::Country-A||Country-B]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "City-A#0##",
+ "City-B#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9 conjunctive subobject subquery ",
+ "condition": "[[Has subobject::<q>[[Has arbitrary number::42]][[Has arbitrary text::abc]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "City-A#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10",
+ "condition": "[[Has subobject::<q>[[Has arbitrary number::42||1001]] OR [[Has arbitrary text::abc||def]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "City-A#0##",
+ "City-B#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#11 disjunctive subobject subquery, #625",
+ "condition": "[[Has subobject::<q>[[Has area::891.85 km ²]] OR [[Has arbitrary text::abc||def]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "City-A#0##",
+ "City-B#0##",
+ "City-C#0##"
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0607.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0607.json
new file mode 100644
index 00000000..0d9e50fd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0607.json
@@ -0,0 +1,116 @@
+{
+ "description": "Test `_wpg`/`_dat`/`_num`/`_txt` subquery example",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project manager",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project pool",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project assistant",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project name",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project due date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project level access",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has name",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "P-100",
+ "contents": "[[Category:Project]][[Has project name::P-100]][[Has project due date::10/30/2015]]"
+ },
+ {
+ "page": "山田一郎",
+ "contents": "[[Category:Project assistant]] [[Has name::{{PAGENAME}}]] [[Has project level access::5]]"
+ },
+ {
+ "page": "Clara Young",
+ "contents": "[[Category:Project assistant]] [[Has name::{{PAGENAME}}]] [[Has project level access::6]]"
+ },
+ {
+ "page": "John Doe",
+ "contents": "[[Category:Person]] [[Category:Project manager]] [[Has name::{{PAGENAME}}]] [[Has project assistant::Clara Young]] [[Has project assistant::山田一郎]]"
+ },
+ {
+ "page": "Example/0607/PP-100",
+ "contents": "{{#subobject:|@category=Project pool |Has project=P-100 |Has project manager=John Doe |Has project pool={{PAGENAME}} }} {{#subobject:|@category=Project pool |Has project=P-200 |Has project manager=John Doe |Has project pool={{PAGENAME}} }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 conjunctive/disjunctive subquery; What projects are due where Jon Doe is assigned (with either Clara Young or 山田一郎); Query-Size:15 / Query-Depth:2",
+ "condition": "[[Category:Project pool]] [[Has project::<q>[[Has project name::P-100]] [[Has project due date::>9/24/2015]]</q>]] [[Has project manager::<q>[[Has name::John Doe]] [[Has project assistant::山田一郎]] OR [[Has name::John Doe]] [[Has project assistant::Clara Young]]</q>]]",
+ "printouts": [
+ "Has project manager",
+ "Has project"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/0607/PP-100#0##_43aaa7182890fb917e6cc82bf6083abb"
+ ],
+ "dataitems": [
+ {
+ "type": "_wpg",
+ "value": "John_Doe#0##"
+ },
+ {
+ "type": "_wpg",
+ "value": "P-100#0##"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 conjunctive subquery; What projects are due where Jon Doe is assigned (together with a level 5 assistant); Query-Size:12 / Query-Depth:3",
+ "condition": "[[Category:Project pool]] [[Has project::<q>[[Has project name::P-100]] [[Has project due date::>9/24/2015]]</q>]] [[Has project manager::<q>[[Has name::John Doe]] [[Has project assistant.Has project level access::5]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/0607/PP-100#0##_43aaa7182890fb917e6cc82bf6083abb"
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0608.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0608.json
new file mode 100644
index 00000000..41ab93e0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0608.json
@@ -0,0 +1,123 @@
+{
+ "description": "Test `_wpg` for single value approximate (`~/!~`) queries (#1246)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has example page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/0608/1/1",
+ "contents": "[[Category:0608-1]]"
+ },
+ {
+ "page": "Example/0608/1/2",
+ "contents": "[[Category:0608-2]]"
+ },
+ {
+ "page": "Example/0608/3",
+ "contents": "[[Category:0608-3]] [[Has example page::Example/0608/3]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Example/0608/1/1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/0608/1/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Example/0608/1/1]] OR [[Example/0608/3]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/0608/1/1#0##",
+ "Example/0608/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[~Example/0608/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/0608/1/1#0##",
+ "Example/0608/1/2#0##",
+ "Example/0608/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[~Example/0608/*]][[!~Example/0608/1/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/0608/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[~Example/0608/*]] [[Category:0608-2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/0608/1/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[~Example/0608/*]] [[Has example page::Example/0608/3]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/0608/3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0609.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0609.json
new file mode 100644
index 00000000..78a74c37
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0609.json
@@ -0,0 +1,78 @@
+{
+ "description": "Test `_wpg` for single value approximate (`~/!~`) queries with conjunctive category hierarchy (#1246, en, skip virtuoso)",
+ "setup": [
+ {
+ "page": "Example/0609/1",
+ "contents": "[[Category:0609-1]]"
+ },
+ {
+ "page": "Example/0609/2",
+ "contents": "[[Category:0609-2]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "0609-1",
+ "contents": "[[Category:0609]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "0609-2",
+ "contents": "[[Category:0609]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[~*0609*]][[Category:0609]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/0609/1#0##",
+ "Example/0609/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[~*0609*]][[Category:0609]][[!~*0609*/2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/0609/1#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/subcategory hierarchies are not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0610.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0610.json
new file mode 100644
index 00000000..2797e802
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0610.json
@@ -0,0 +1,94 @@
+{
+ "description": "Test `_wpg` range queries (#1291, `smwStrictComparators=false`, skip virtuoso)",
+ "setup": [
+ {
+ "page": "Example/Q0610-A",
+ "contents": "[[Category:Q0610]]"
+ },
+ {
+ "page": "Example/Q0610-AAA",
+ "contents": "[[Category:Q0610]]"
+ },
+ {
+ "page": "Example/Q0610-BBB",
+ "contents": "[[Category:Q0610]]"
+ },
+ {
+ "page": "Example/Q0610-CCC",
+ "contents": "[[Category:Q0610]]"
+ },
+ {
+ "page": "Example/Q0610-DDD",
+ "contents": "[[Category:Q0610]]"
+ },
+ {
+ "page": "Example/Q0610-ZZZ",
+ "contents": "[[Category:Q0610-Z]] {{DEFAULTSORT:Example/Q0610-CCC}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 range >A <C (non strict comparator)",
+ "condition": "[[Category:Q0610]] [[>Example/Q0610-A]] [[<Example/Q0610-C]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0610-A#0##",
+ "Example/Q0610-AAA#0##",
+ "Example/Q0610-BBB#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 range >AA <CCC (non strict comparator)",
+ "condition": "[[Category:Q0610]] [[>Example/Q0610-AA]] [[<Example/Q0610-CCC]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0610-AAA#0##",
+ "Example/Q0610-BBB#0##",
+ "Example/Q0610-CCC#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 range >AA <CCC (non strict comparator), default sort change includes ZZZ object",
+ "condition": "<q>[[Category:Q0610]] OR [[Category:Q0610-Z]]</q> [[>Example/Q0610-AA]] [[<Example/Q0610-CCC]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/Q0610-AAA#0##",
+ "Example/Q0610-BBB#0##",
+ "Example/Q0610-CCC#0##",
+ "Example/Q0610-ZZZ#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 doesn't understand ranges, Failed asserting that 5 matches expected 3"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0611.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0611.json
new file mode 100644
index 00000000..d879ea63
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0611.json
@@ -0,0 +1,62 @@
+{
+ "description": "Test `_wpg` namespace any value queries (#1301, en)",
+ "setup": [
+ {
+ "namespace": "NS_HELP",
+ "page": "Example/Q0611/1",
+ "contents": "[[Category:Q0611]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "Example/Q0611/2",
+ "contents": "[[Category:Q0611]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "Example/Q0611/3",
+ "contents": "#REDIRECT [[Example/Q0611/4]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "do-delete": true,
+ "page": "Example/Q0611/4",
+ "contents": "[[Category:Q0611]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Help:+]] [[Category:Q0611]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0611/1#12##",
+ "Example/Q0611/2#12##"
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ },
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0612.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0612.json
new file mode 100644
index 00000000..928bd4da
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0612.json
@@ -0,0 +1,100 @@
+{
+ "description": "Test `_wpg` object value that contains `=` (equals sign) (#640, #710, #1542, #1645, #3560)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/Q0612/1(=)",
+ "contents": "[[Category:Q0612]] [[Has page::{{FULLPAGENAME}}]]"
+ },
+ {
+ "page": "Example/Q0612/-3D=",
+ "contents": "[[Category:Q0612]] [[Has page::{{FULLPAGENAME}}]]"
+ },
+ {
+ "page": "Example/Q0612/Q1",
+ "contents": "{{#show: Example/Q0612/1(=) |?Has page |link=none }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#2 #show not be disturbed by `=`",
+ "subject": "Example/Q0612/Q1",
+ "assert-output": {
+ "to-contain": [
+ "Example/Q0612/1(=)"
+ ],
+ "not-contain": [
+ "&quot;:&quot; cannot be used as a page name in this wiki."
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Category:Q0612]] [[Example/Q0612/1(=)]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0612/1(=)#0##"
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Category:Q0612]] [[Has page::Example/Q0612/1(=)]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0612/1(=)#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Category:Q0612]] [[Has page::Example/Q0612/-3D=]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0612/-3D=#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ },
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0613.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0613.json
new file mode 100644
index 00000000..15a030f1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0613.json
@@ -0,0 +1,182 @@
+{
+ "description": "Test single value (`~/!~`/`<`/`>`) queries on namespaced entity (#1652, `NS_HELP`, `smwStrictComparators=false`, skip-on virtuoso)",
+ "setup": [
+ {
+ "page": "ABC",
+ "contents": "[[Category:0613]] (control group)"
+ },
+ {
+ "page": "ABB",
+ "contents": "[[Category:0613]] (control group)"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "ABC",
+ "contents": "[[Category:0613]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "ABB",
+ "contents": "[[Category:0613]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "AAB",
+ "contents": "[[Category:0613]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Help:~A*B]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "AAB#12##",
+ "ABB#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[~Help:A*B]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "AAB#12##",
+ "ABB#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Help:!~A*B]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "ABC#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[!~Help:A*B]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "ABC#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Help:>AB]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "ABC#12##",
+ "ABB#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[>Help:AB]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "ABC#12##",
+ "ABB#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6",
+ "condition": "[[Help:<AB]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "AAB#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7",
+ "condition": "[[<Help:AB]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "AAB#12##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8",
+ "condition": "[[<Help:<AB]] [[Category:0613]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 does not like this test"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0614.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0614.json
new file mode 100644
index 00000000..16f3ecf8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0614.json
@@ -0,0 +1,109 @@
+{
+ "description": "Test query with category hierarchy depth (#2662, `wgContLang=en`, `smwgQSubpropertyDepth`, `smwgQSubcategoryDepth`, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0614",
+ "contents": "Super class"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0614/1",
+ "contents": "[[Category:Q0614]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0614/1/2",
+ "contents": "[[Category:Q0614/1]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0614/1/2/3",
+ "contents": "[[Category:Q0614/1/2]]"
+ },
+ {
+ "page": "Example/Q0614/1",
+ "contents": "[[Category:Q0614]]"
+ },
+ {
+ "page": "Example/Q0614/1/2",
+ "contents": "[[Category:Q0614/1]]"
+ },
+ {
+ "page": "Example/Q0614/1/2/3",
+ "contents": "[[Category:Q0614/1/2]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 select all members",
+ "condition": "[[Category:Q0614]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0614/1#0##",
+ "Example/Q0614/1/2#0##",
+ "Example/Q0614/1/2/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 depth=0",
+ "condition": "[[Category:Q0614|+depth=0]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0614/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 depth=1",
+ "condition": "[[Category:Q0614|+depth=1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0614/1#0##",
+ "Example/Q0614/1/2#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/subcategory hierarchies are not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0615.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0615.json
new file mode 100644
index 00000000..c0bf8673
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0615.json
@@ -0,0 +1,148 @@
+{
+ "description": "Test query with property hierarchy depth (#2662, `wgContLang=en`, `smwgQSubpropertyDepth`, `smwgQSubcategoryDepth`, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Q0615",
+ "contents": "Super property"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Q0615/1",
+ "contents": "[[Subproperty of::Q0615]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Q0615/1/2",
+ "contents": "[[Subproperty of::Q0615/1]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Q0615/1/2/3",
+ "contents": "[[Subproperty of::Q0615/1/2]]"
+ },
+ {
+ "page": "Example/Q0615/1",
+ "contents": "[[Q0615::123]]"
+ },
+ {
+ "page": "Example/Q0615/1/2.1",
+ "contents": "[[Q0615/1::123]]"
+ },
+ {
+ "page": "Example/Q0615/1/2.2",
+ "contents": "[[Q0615/1::456]]"
+ },
+ {
+ "page": "Example/Q0615/1/2/3",
+ "contents": "[[Q0615/1/2::123]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 select all members on discrete value",
+ "condition": "[[Q0615::123]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0615/1#0##",
+ "Example/Q0615/1/2.1#0##",
+ "Example/Q0615/1/2/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 select all members on any value",
+ "condition": "[[Q0615::+]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/Q0615/1#0##",
+ "Example/Q0615/1/2.1#0##",
+ "Example/Q0615/1/2.2#0##",
+ "Example/Q0615/1/2/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 depth=0",
+ "condition": "[[Q0615::123|+depth=0]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0615/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 depth=1 on discrete value",
+ "condition": "[[Q0615::123|+depth=1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0615/1#0##",
+ "Example/Q0615/1/2.1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 depth=1 on any value",
+ "condition": "[[Q0615::+|+depth=1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0615/1#0##",
+ "Example/Q0615/1/2.1#0##",
+ "Example/Q0615/1/2.2#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/subcategory hierarchies are not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0616.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0616.json
new file mode 100644
index 00000000..62793a37
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0616.json
@@ -0,0 +1,128 @@
+{
+ "description": "Test `in:` syntax on `_txt`, `_dat`, and `_num` values",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/Q0616/1",
+ "contents": "[[Has date::1 Jan 1970 12:00]] [[Category:0616]]"
+ },
+ {
+ "page": "Example/Q0616/2",
+ "contents": "[[Has date::1 Jan 1971 12:00]] [[Category:0616]]"
+ },
+ {
+ "page": "Example/Q0616/3",
+ "contents": "[[Has text::abc def foo]] [[Category:0616]]"
+ },
+ {
+ "page": "Example/Q0616/4",
+ "contents": "[[Has text::abc foo]] [[Category:0616]]"
+ },
+ {
+ "page": "Example/Q0616/5",
+ "contents": "[[Has number::50]] [[Category:0616]]"
+ },
+ {
+ "page": "Example/Q0616/6",
+ "contents": "[[Has number::99]] [[Category:0616]]"
+ },
+ {
+ "page": "Example/Q0616/7",
+ "contents": "[[Has number::100]] [[Category:0616]]"
+ },
+ {
+ "page": "Example/Q0616/8",
+ "contents": "[[Has number::-20]] [[Category:0616]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (in: on date converted to `[[Has date:: [[≥1970]] [[<<1 January 1971 00:00:00]] ]]`)",
+ "condition": "[[Has date::in:1970]] [[Category:0616]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0616/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (in: on text converted to `[[Has text::~*abc d*]]`)",
+ "condition": "[[Has text::in:abc d]] [[Category:0616]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0616/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (in: on number converted to `[[Has number:: [[≥0]] [[≤99]] ]]`)",
+ "condition": "[[Has number::in:99]] [[Category:0616]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0616/5#0##",
+ "Example/Q0616/6#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (in: on number converted to `[[Has number:: [[≥-100]] [[≤0]] ]]`)",
+ "condition": "[[Has number::in:-100]] [[Category:0616]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0616/8#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0617.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0617.json
new file mode 100644
index 00000000..1476dc27
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0617.json
@@ -0,0 +1,127 @@
+{
+ "description": "Test range `<>` syntax on `_num` (float,double), `_dat` (millisec) values (`smwStrictComparators=true`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/Q0617/1",
+ "contents": "[[Has number::100.1000008]] [[Category:Q0617]]"
+ },
+ {
+ "page": "Example/Q0617/2",
+ "contents": "[[Has number::100.1000009]] [[Category:Q0617]]"
+ },
+ {
+ "page": "Example/Q0617/3",
+ "contents": "[[Has number::100.1000010]] [[Category:Q0617]]"
+ },
+ {
+ "page": "Example/Q0617/4",
+ "contents": "[[Has date::1 Jan 2200 12:00:00.100]] [[Category:Q0617]]"
+ },
+ {
+ "page": "Example/Q0617/5",
+ "contents": "[[Has date::1 Jan 2200 12:00:00.200]] [[Category:Q0617]]"
+ },
+ {
+ "page": "Example/Q0617/6",
+ "contents": "[[Has date::1 Jan 2200 12:00:00.300]] [[Category:Q0617]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (>100.1000008 AND <100.1000010)",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.+ just can't cope with this query!"
+ },
+ "condition": "[[Has number::>100.1000008]] [[Has number::<100.1000010]] [[Category:Q0617]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0617/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (>=100.1000008 AND <100.1000010)",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.+ just can't cope with this query!"
+ },
+ "condition": "[[Has number::>=100.1000008]] [[Has number::<100.1000010]] [[Category:Q0617]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0617/1#0##",
+ "Example/Q0617/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (1 Jan 2200 12:00:00.100)",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.+ just can't cope with this query!"
+ },
+ "condition": "[[Has date::1 Jan 2200 12:00:00.100]] [[Category:Q0617]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0617/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (>1 Jan 2200 12:00:00 AND <1 Jan 2200 12:00:00.200)",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.+ just can't cope with this query!"
+ },
+ "condition": "[[Has date::>1 Jan 2200 12:00:00]][[Has date::<1 Jan 2200 12:00:00.200]] [[Category:Q0617]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0617/4#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": true,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0618.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0618.json
new file mode 100644
index 00000000..ba1e5046
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0618.json
@@ -0,0 +1,133 @@
+{
+ "description": "Test deep subqueries (Friends of friends) (`smwgQMaxDepth`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Age",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Material status",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/Q0618/1",
+ "contents": {
+ "import-from": "/../Fixtures/q-0618.persons.txt"
+ }
+ },
+ {
+ "page": "Example/Q0618/2",
+ "contents": {
+ "import-from": "/../Fixtures/q-0618.visits.txt"
+ }
+ },
+ {
+ "page": "Example/Q0618/3",
+ "contents": {
+ "import-from": "/../Fixtures/q-0618.friends.txt"
+ }
+ },
+ {
+ "page": "Example/Q0618/4a",
+ "contents": "{{#ask: [[Person::Andy Mars]][[Age::+]] |?Age |mainlabel=- |headers=hide }} {{#ask: [[Person::Andy Mars]][[Age::+]] |?Age |mainlabel=- |headers=hide |format=debug }}"
+ },
+ {
+ "page": "Example/Q0618/4b",
+ "contents": "{{#ask: [[-Person::<q>[[Person.-Has friend.Person::Andy Mars]][[Age::>>{{#ask: [[Person::Andy Mars]][[Age::+]] |?Age |mainlabel=- |headers=hide }} ]]</q>]] }} {{#ask: [[-Person::<q>[[Person.-Has friend.Person::Andy Mars]][[Age::>>{{#ask: [[Person::Andy Mars]][[Age::+]] |?Age |mainlabel=- |headers=hide }} ]]</q>]] |format=debug}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (Show Friends of friends from Andy Mars)",
+ "condition": "[[-Has friend.Person.-Has friend.Person::Andy Mars]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 7,
+ "results": [
+ "Charlotte Beans#0##",
+ "Evelyne Lynn#0##",
+ "James Ross#0##",
+ "Mandy Rose#0##",
+ "Michael Chester#0##",
+ "Rosalia Alvarez#0##",
+ "Yumi Tanaka#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (Show Friends of friends from Andy Mars who are single and over 30)",
+ "condition": "[[-Person:: <q>[[Person.-Has friend.Person.-Has friend.Person::Andy Mars]] [[Material status::single]][[Age::> 30]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Michael Chester#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (Show Friends who have been to places Andy Mars has visited)",
+ "condition": "[[-Person.Place visited::<q>[[-Place visited.Person::<q>[[-Has friend.Person::Andy Mars]]</q>]][[-Place visited::<q>[[Person::Andy Mars]]</q>]]</q>]] [[!Andy Mars]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 7,
+ "results": [
+ "Charles Banning#0##",
+ "Charlotte Beans#0##",
+ "John Maier#0##",
+ "Kevin Mikaelson#0##",
+ "Mike Bloom#0##",
+ "Rosalia Alvarez#0##",
+ "Yumi Tanaka#0##"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (age)",
+ "subject": "Example/Q0618/4a",
+ "assert-output": {
+ "to-contain": [
+ "32"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (Show Friends from Andy Mars that are older has him)",
+ "subject": "Example/Q0618/4b",
+ "assert-output": {
+ "to-contain": [
+ "Charles Banning"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgQMaxDepth": 16,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0619.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0619.json
new file mode 100644
index 00000000..be97b411
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0619.json
@@ -0,0 +1,80 @@
+{
+ "description": "Test `_wpg` user case (#2982)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/Q0619/1",
+ "contents": "[[Has page::userCase]]"
+ },
+ {
+ "page": "Example/Q0619/user Case",
+ "contents": "[[Has page::Example/Q0619/1]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (userCase, UserCase on _wpg type)",
+ "condition": "[[Has page::userCase]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0619/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (userCase, UserCase on _wpg type)",
+ "condition": "[[Has page::UserCase]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0619/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[~*user Case*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0619/user Case#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ },
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0620.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0620.json
new file mode 100644
index 00000000..b73064f7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0620.json
@@ -0,0 +1,134 @@
+{
+ "description": "Test `_wpg` and category using subquery construct",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q0620/1",
+ "contents": "[[Has page::Q0620/1]] [[Category:Q0620]]"
+ },
+ {
+ "page": "Q0620/2",
+ "contents": "[[Category:Q0620]]"
+ },
+ {
+ "page": "Q0620/3",
+ "contents": "[[Has page::Q0620/1]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (match all with `Has page::Q0620/1`)",
+ "condition": "[[Has page::<q>[[Category:Q0620]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0620/1#0##",
+ "Q0620/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has page::<q>[[Category:Q0620]]</q>]] [[Category:Q0620]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0620/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Has page::<q>[[Has page::<q>[[Category:Q0620]]</q>]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0620/1#0##",
+ "Q0620/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Has page::<q>[[Has page::<q>[[Category:Q0620]]</q>]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0620/1#0##",
+ "Q0620/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Has page.Has page::<q>[[Category:Q0620]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0620/1#0##",
+ "Q0620/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "skip-on": {
+ "elastic": [ "not", "`Category:!` only works with ES." ]
+ },
+ "condition": "[[Has page::<q>[[Has page::<q>[[Category:Q0620]]</q>]]</q>]] [[Category:!Q0620]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0620/3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgQSubcategoryDepth": 10
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0621.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0621.json
new file mode 100644
index 00000000..23d9b654
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0621.json
@@ -0,0 +1,105 @@
+{
+ "description": "Test `_wpg` and namespace using subquery construct",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "Q0621",
+ "contents": "[[Has page::Q0621/1]] [[Category:Q0621]]"
+ },
+ {
+ "namespace": "NS_HELP",
+ "page": "Q0621/1",
+ "contents": "[[Has page::Q0621/2]] [[Category:Q0621]]"
+ },
+ {
+ "page": "Q0621/1",
+ "contents": "[[Has page::Help:Q0621]]"
+ },
+ {
+ "page": "Q0621/2",
+ "contents": "[[Has page::Q0621/2]] [[Category:Q0621/1]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has page::<q>[[Help:+]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0621/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has page::<q>[[Help:+]] [[Has page::+]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0621/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Has page::<q>[[Help:+]] [[Has page::+]] [[Category:Q0621]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0621/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[-Has page::<q>[[Help:+]] [[Has page::<q> [[Category:Q0621/1]]</q>]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0621/2#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ },
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0622.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0622.json
new file mode 100644
index 00000000..95d478a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0622.json
@@ -0,0 +1,71 @@
+{
+ "description": "Test query with category hierarchy",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0622/A",
+ "contents": "[[Category:Q0622]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0622/B",
+ "contents": "[[Category:Q0622/A]] [[Category:Q0622/C]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0622/C",
+ "contents": "[[Category:Q0622]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Q0622",
+ "contents": "[[Category:Q0622]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Category:Q0622]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0622#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ },
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/subcategory hierarchies are not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0623.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0623.json
new file mode 100644
index 00000000..4ef1d39c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0623.json
@@ -0,0 +1,85 @@
+{
+ "description": "Test query with `_SUBC`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0623",
+ "contents": ""
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0623/1",
+ "contents": "[[Category:Q0623]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0623/1/1",
+ "contents": "[[Category:Q0623/1]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0623/1/2",
+ "contents": "[[Category:Q0623/1]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (without `Category:` namespace, #3550)",
+ "condition": "[[Subcategory of::Q0623/1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0623/1/1#14##",
+ "Q0623/1/2#14##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (with `Category:` namespace)",
+ "condition": "[[Subcategory of::Category:Q0623/1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0623/1/1#14##",
+ "Q0623/1/2#14##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_HELP": true
+ },
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0701.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0701.json
new file mode 100644
index 00000000..8d81e881
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0701.json
@@ -0,0 +1,186 @@
+{
+ "description": "Test `_uri` with some annotation/search pattern (T45264, #679)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Page-with-url-1",
+ "contents": "[[Has url::http://example.org/aaa/bbb#ccc]]"
+ },
+ {
+ "page": "Page-with-url-2",
+ "contents": "[[Has url::http://acme.test/api?query=!_:;@* #Foo&=%20-3DBar]]"
+ },
+ {
+ "page": "Page-with-url-3",
+ "contents": "[[Has url::http://example.org/よã†ã“ã#-{}]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has url::http://example.org/aaa/bbb#ccc]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-url-1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has url",
+ "value": "http://example.org/aaa/bbb#ccc"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has url::http://acme.test/api?query=!_:;@*_#Foo&=_-3DBar]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-url-2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has url",
+ "value": "http://acme.test/api?query=%21_:%3B@%2A_#Foo&=_-3DBar"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Has url::~*example.org/*]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Page-with-url-1#0##",
+ "Page-with-url-3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Has url::~*ccc*]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-url-1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Has url::~http://*query=*]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-url-2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[Has url::~http://*query=*]] OR [[Has url::~*ccc*]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2",
+ "results": [
+ "Page-with-url-1#0##",
+ "Page-with-url-2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6",
+ "condition": "[[Has url::http://example.org/よã†ã“ã#-{}]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-url-3#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has url",
+ "value": "http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D#-%7B%7D"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7",
+ "condition": "[[Has url::http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D#-%7B%7D]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page-with-url-3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0702.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0702.json
new file mode 100644
index 00000000..c195974b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0702.json
@@ -0,0 +1,177 @@
+{
+ "description": "Test `_uri` with additional annotation/search (#1129)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has telephone number",
+ "contents": "[[Has type::Telephone number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has email",
+ "contents": "[[Has type::Email]]"
+ },
+ {
+ "page": "Page/07/02/1",
+ "contents": "[[Has telephone number::+1-2012-555-0123]]"
+ },
+ {
+ "page": "Page/07/02/2",
+ "contents": "[[Has telephone number::+1-2012-555-5555]]"
+ },
+ {
+ "page": "Page/07/02/3",
+ "contents": "[[Has email::Lorem@ipsum.org]]"
+ },
+ {
+ "page": "Page/07/02/4",
+ "contents": "[[Has email::Lorem@123.org]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 search phone number +1-2012-555-5555",
+ "condition": "[[Has telephone number::+1-2012-555-5555]]",
+ "printouts": [
+ "Has telephone number"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page/07/02/2#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has telephone number",
+ "value": "tel:+1-2012-555-5555"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 search phone number that contains 123",
+ "condition": "[[Has telephone number::~*123*]]",
+ "printouts": [
+ "Has telephone number"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page/07/02/1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has telephone number",
+ "value": "tel:+1-2012-555-0123"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 search phone number that contains 555",
+ "condition": "[[Has telephone number::~*555*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "2",
+ "results": [
+ "Page/07/02/1#0##",
+ "Page/07/02/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 search e-mail address Lorem@ipsum.org",
+ "condition": "[[Has email::Lorem@ipsum.org]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page/07/02/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 search e-mail address that contains 123.org",
+ "condition": "[[Has email::~*123.org]]",
+ "printouts": [
+ "Has email"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page/07/02/4#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has email",
+ "value": "mailto:Lorem@123.org"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 search phone number that does not contain 123",
+ "condition": "[[Has telephone number::!~*123*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page/07/02/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 search e-mail address that does not contain 123.org",
+ "condition": "[[Has email::!~*123.org]]",
+ "printouts": [
+ "Has email"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": "1",
+ "results": [
+ "Page/07/02/3#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has email",
+ "value": "mailto:Lorem@ipsum.org"
+ }
+ ]
+ }
+ }
+ ],
+ "settings": [],
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0703.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0703.json
new file mode 100644
index 00000000..c360aca1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0703.json
@@ -0,0 +1,77 @@
+{
+ "description": "Test to map `Foaf` property from back-end / using a localized predefined property `A le type@fr` (en)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import foaf",
+ "contents": "http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name|Type:Text\n homepage|Type:URL\n mbox|Type:Email\n mbox_sha1sum|Type:Text\n depiction|Type:URL\n phone|Type:Text\n Person|Category\n Organization|Category\n knows|Type:Page\n member|Type:Page\n"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:homepage",
+ "contents": "[[Imported from::foaf:homepage]] [[Category:Import]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has type::+]] [[Category:Import]]",
+ "printouts": [
+ "Has type"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Foaf:homepage#102##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has type",
+ "value": "URL"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (A le type@fr == Has type)",
+ "condition": "[[A le type@fr::+]] [[Category:Import]]",
+ "printouts": [
+ "A le type@fr"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Foaf:homepage#102##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has type",
+ "value": "URL"
+ }
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0704.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0704.json
new file mode 100644
index 00000000..b4d23f5e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0704.json
@@ -0,0 +1,52 @@
+{
+ "description": "Test `_uri` long URL (255+) (#1872)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/Q0704/1",
+ "contents": "[[Has url::http://example.org/TBgcHiQBTvpV3XkFiRpMcV1KQoZvQXFyiQUQMM2RoYUyJaRoSyKnsQTWwia3HATd4YVmd8BZgkL2LfL0Q6rP5E90A4IuV6uKdYjL3nxZvx0pbc3tbxwa6jMW1JDNxusaKQ52ftRS7DCEY1IPTRZnuRMLPgWYwLOsEAebOsxD7BBL9IK3Z2Osfh9s0FC1SUwCVdKcLkBgurXKGi99s61qnAU2zWFXBUCEzID6533LeaHCBKW8\\/\\i2BgTK2tv65LHO6zB-larger%&`^Than255ö/ä/ü/è/é]]"
+ },
+ {
+ "page": "Example/Q0704/Q.1",
+ "contents": "{{#ask: [[Has url::~*Than255]] |?Has url}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 URL 255+ chars",
+ "condition": "[[Has url::~*Than255*]]",
+ "printouts": [
+ "Has url"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0704/1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Has url",
+ "value": "http://example.org/TBgcHiQBTvpV3XkFiRpMcV1KQoZvQXFyiQUQMM2RoYUyJaRoSyKnsQTWwia3HATd4YVmd8BZgkL2LfL0Q6rP5E90A4IuV6uKdYjL3nxZvx0pbc3tbxwa6jMW1JDNxusaKQ52ftRS7DCEY1IPTRZnuRMLPgWYwLOsEAebOsxD7BBL9IK3Z2Osfh9s0FC1SUwCVdKcLkBgurXKGi99s61qnAU2zWFXBUCEzID6533LeaHCBKW8%5C/%5Ci2BgTK2tv65LHO6zB-larger%&%60%5EThan255%C3%B6/%C3%A4/%C3%BC/%C3%A8/%C3%A9"
+ }
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEnabledFulltextSearch": true,
+ "smwgFulltextDeferredUpdate": false
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0801.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0801.json
new file mode 100644
index 00000000..0abdab74
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0801.json
@@ -0,0 +1,47 @@
+{
+ "description": "Test `_INST` query (#1004, en)",
+ "setup": [
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Foo",
+ "contents": ""
+ },
+ {
+ "page": "Page-with-category",
+ "contents": "[[Category:Foo]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 query pages with annotated category",
+ "condition": "[[Category:Foo]]",
+ "printouts": [
+ "_INST"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page-with-category#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "_INST",
+ "value": "Foo"
+ }
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0802.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0802.json
new file mode 100644
index 00000000..9dab306f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0802.json
@@ -0,0 +1,160 @@
+{
+ "description": "Test `_INST`/`_SUBC` queries (#1005, en, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Foo",
+ "contents": ""
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Bar",
+ "contents": "[[Category:Foo]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Bam",
+ "contents": "[[Category:Foo]]"
+ },
+ {
+ "page": "Page-annotated-with-subcategory",
+ "contents": "[[Category:Bar]] [[Category:Bam]]"
+ },
+ {
+ "page": "Page-annotated-with-another-subcategory",
+ "contents": "[[Category:Bam]]"
+ },
+ {
+ "page": "Page-annotated-with-supercategory-subcategory",
+ "contents": "[[Category:Foo]] [[Category:Bam]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 query pages with annotated category(subcategory)",
+ "condition": "[[Category:Bar]]",
+ "printouts": [
+ "_INST"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page-annotated-with-subcategory#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "_INST",
+ "value": "Bar"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 disjuntive query for two categories",
+ "condition": "[[Category:Bar]] OR [[Category:Bam]]",
+ "printouts": [
+ "_INST"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Page-annotated-with-subcategory#0##",
+ "Page-annotated-with-another-subcategory#0##",
+ "Page-annotated-with-supercategory-subcategory#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 conjuntive query for two categories",
+ "condition": "[[Category:Bar]][[Category:Bam]]",
+ "printouts": [
+ "_INST"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Page-annotated-with-subcategory#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 find list of subcategories for selected super",
+ "condition": "[[Subcategory of::Category:Foo]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Bar#14##",
+ "Bam#14##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 find the super for a selected subcategory",
+ "condition": "[[-Subcategory of::Category:Bar]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Foo#14##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 disjuntive query for two categories",
+ "condition": "[[Category:Foo]] OR [[Category:Bam]]",
+ "printouts": [
+ "_INST"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Page-annotated-with-subcategory#0##",
+ "Page-annotated-with-another-subcategory#0##",
+ "Page-annotated-with-supercategory-subcategory#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubcategoryDepth": 10
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/subcategory hierarchies are not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0803.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0803.json
new file mode 100644
index 00000000..b7b69adb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0803.json
@@ -0,0 +1,140 @@
+{
+ "description": "Test `_INST`/ Nested category annotation (#1012, en, skip virtuoso) category hierarchy queries",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has trait",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has breed trait",
+ "contents": "[[Has type::Text]] [[Subproperty of::Has trait]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has group",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Animal",
+ "contents": "..."
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Canis",
+ "contents": "is a genus containing ... and is part of the [[Category:Animal]] kingdom."
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Domestic dog",
+ "contents": "[[Category:Canis]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Dog",
+ "contents": "#REDIRECT [[:Category:Domestic dog]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Wolf",
+ "contents": "[[Category:Canis]]"
+ },
+ {
+ "page": "German Shepherd",
+ "contents": "[[Category:Dog]] [[Has breed trait::Herding]] [[Has group::Herding group]]"
+ },
+ {
+ "page": "Dachshund",
+ "contents": "[[Category:Dog]] [[Has breed trait::Hunting]] [[Has group::Hound group]]"
+ },
+ {
+ "page": "Scottish Terrier",
+ "contents": "[[Category:Dog]] [[Has breed trait::Hunting]] [[Has group::Terrier group]]"
+ },
+ {
+ "page": "Irish Setter",
+ "contents": "[[Category:Dog]] [[Has breed trait::Sporting]] [[Has group::Sporting group]]"
+ },
+ {
+ "page": "Gray wolf",
+ "contents": "[[Category:Wolf]] [[Has trait::Hunting]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 all (max 10) animals with herding traits",
+ "condition": "[[Category:Animal]] AND [[Has trait::Herding]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "German Shepherd#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 all (max 10) animals with herding or hunting traits",
+ "condition": "[[Category:Animal]] <q>[[Has trait::Herding]] OR [[Has trait::Hunting]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "German Shepherd#0##",
+ "Scottish Terrier#0##",
+ "Dachshund#0##",
+ "Gray wolf#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 all (max 10) animals with herding or hunting traits (compact OR notation)",
+ "condition": "[[Category:Animal]][[Has trait::Herding||Hunting]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "German Shepherd#0##",
+ "Scottish Terrier#0##",
+ "Dachshund#0##",
+ "Gray wolf#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/subcategory hierarchies are not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0804.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0804.json
new file mode 100644
index 00000000..735d2ee3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0804.json
@@ -0,0 +1,34 @@
+{
+ "description": "Test `_INST` with namespace prefix",
+ "setup": [
+ {
+ "page": "Example/Q0804/1",
+ "contents": "[[Category:Help:Q0804]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (Category: is correctly parsed despite the Help: NS prefix)",
+ "condition": "[[Category:Help:Q0804]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0804/1#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "es"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0901.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0901.json
new file mode 100644
index 00000000..017b52f2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0901.json
@@ -0,0 +1,379 @@
+{
+ "description": "Test `_wpg`/`_txt` on various disjunction, conjunction queries (#19, #1060, #1056, #1057)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page-1",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page-2",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text-1",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text-2",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0901-1"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q0901-2"
+ },
+ {
+ "page": "Q0901/1",
+ "contents": "[[Category:Q0901-1]] [[Has page-1::Value 1]][[Has text-1::Value 1]] [[Has text-1::Value 3]]"
+ },
+ {
+ "page": "Q0901/1/1",
+ "contents": "[[Category:Q0901-1]] [[Has page-1::Value 1]][[Has page-2::Value 2]][[Has text-1::Value 1]][[Has text-2::Value 2]]"
+ },
+ {
+ "page": "Q0901/1/2",
+ "contents": "[[Category:Q0901-1]] [[Has page-1::Value 1]][[Has page-1::Value 2]][[Has text-1::Value 1]][[Has text-1::Value 2]]"
+ },
+ {
+ "page": "Q0901/2",
+ "contents": "[[Category:Q0901-1]] [[Has page-2::Value 1]][[Has text-2::Value 1]] [[Has page-1::Value 3]]"
+ },
+ {
+ "page": "Q0901/2/1",
+ "contents": "[[Category:Q0901-1]] [[Has page-2::Value 1]][[Has page-2::Value 2]][[Has text-2::Value 1]][[Has text-2::Value 2]]"
+ },
+ {
+ "page": "Q0901/3/1",
+ "contents": "[[Category:Q0901-1]] [[Has page-2::Q0901/1/2]]"
+ },
+ {
+ "page": "Q0901/3/2",
+ "contents": "[[Category:Q0901-2]] [[Has page-2::Q0901/2/1]]"
+ },
+ {
+ "page": "Q0901/4/1",
+ "contents": "[[Category:Q0901-1]] [[Has page-1::Q0901/3/2]]"
+ },
+ {
+ "page": "Q0901/4/2",
+ "contents": "[[Category:Q0901-2]] [[Has page-1::Q0901/3/2]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 simple conjection page/text value",
+ "condition": "[[Has page-1::Value 1]] AND [[Has text-1::Value 1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/1/1#0##",
+ "Q0901/1/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 simple conjection page/text value",
+ "condition": "[[Has page-1::Value 1]] AND [[Has text-1::Value 1]] AND [[Has page-2::+]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0901/1/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 simple conjection page/text for multiple value",
+ "condition": "[[Has page-1::Value 1]] AND [[Has text-1::Value 1||Value2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/1/1#0##",
+ "Q0901/1/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 equivalent to #2",
+ "condition": "[[Has page-1::Value 1]] AND <q>[[Has text-1::Value 1]] OR [[Has text-1::Value 2]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/1/1#0##",
+ "Q0901/1/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Has page-1::Value 1]] AND <q>[[Has text-1::Value 1]] OR [[Has page-2::Value 2]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/1/1#0##",
+ "Q0901/1/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[Category:Q0901-1]] AND <q>[[Has text-1::Value 1||Value 2]] OR [[Has page-2::Value 1||Value 2]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 5,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/1/1#0##",
+ "Q0901/1/2#0##",
+ "Q0901/2#0##",
+ "Q0901/2/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6",
+ "condition": "[[Category:Q0901-1]] AND <q>[[Has text-2::Value 1||Value 2]] AND <q>[[Has page-2::Value 1]] AND [[Has page-2::Value 2]]</q></q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0901/2/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7",
+ "condition": "<q>[[Category:Q0901-1]] OR [[Category:Q0901-2]]</q> AND [[Has page-2::<q> [[Has text-1::Value 1]] OR [[Has text-2::Value 2]] </q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0901/3/1#0##",
+ "Q0901/3/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8 equivalent to #7",
+ "condition": "[[Category:Q0901-1||Q0901-2]] AND [[Has page-2::<q> [[Has text-1::Value 1]] OR [[Has text-2::Value 2]] </q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0901/3/1#0##",
+ "Q0901/3/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9",
+ "condition": "[[Has page-1::<q> [[Has page-2::<q> [[Has text-1::Value 1]] OR [[Has text-2::Value 2]] </q>]] </q> ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0901/4/1#0##",
+ "Q0901/4/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10 equivalent to #9 only in chain notation",
+ "condition": "[[Has page-1.Has page-2:: <q> [[Has text-1::Value 1]] OR [[Has text-2::Value 2]]</q> ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0901/4/1#0##",
+ "Q0901/4/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#11",
+ "condition": "[[Category:Q0901-1]] [[Has page-1.Has page-2:: <q> [[Has text-1::Value 1]] OR <q>[[Has text-2::Value 2]][[Has page-2::Value 2]]</q></q> ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0901/4/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#12",
+ "condition": "[[Category:Q0901-1||Q0901-2]] AND [[Has page-1.Has page-2:: <q><q>[[Has text-1::Value 1]][[Has page-2::Value 1]]</q> OR <q>[[Has text-2::Value 2]][[Has page-2::Value 2]]</q></q> ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0901/4/1#0##",
+ "Q0901/4/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#13, see issue #19",
+ "condition": "[[Has page-1::Value 1||Value 2]] [[Has text-1::Value 1||Value 2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/1/1#0##",
+ "Q0901/1/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#14 equivalent to #13",
+ "condition": "<q>[[Has page-1::Value 1]] OR [[Has page-1::Value 2]]</q> AND <q>[[Has text-1::Value 1]] OR [[Has text-1::Value 2]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/1/1#0##",
+ "Q0901/1/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#15",
+ "condition": "<q>[[Has page-1::Value 1]] OR [[Has page-2::Value 1]]</q> AND <q>[[Has text-1::Value 1]] OR [[Has text-2::Value 1]]</q> AND <q>[[Has text-1::Value 3]] OR [[Has page-1::Value 3]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0901/1#0##",
+ "Q0901/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#16",
+ "condition": "[[Has page-2:: <q>[[Has page-1::Value 1||Value 2]] [[Has text-1::Value 1||Value 2]]</q> ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0901/3/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#17",
+ "condition": "[[Has page-2:: <q>[[Has page-1::Value 1||Value 2]] [[Has text-1::Value 1||Value 2]]</q> || <q> [[Has page-2::Value 1||Value 2]]</q> ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q0901/3/1#0##",
+ "Q0901/3/2#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0902.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0902.json
new file mode 100644
index 00000000..0d0c7be7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0902.json
@@ -0,0 +1,65 @@
+{
+ "description": "Test `_txt` to correctly apply parentheses for somehting like (a OR b OR c) AND d (#556)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has conference type",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Conference-1",
+ "contents": "[[Has conference type::Presentation]], [[Has conference type::Tutorial]]"
+ },
+ {
+ "page": "Conference-2",
+ "contents": "[[Has conference type::Tutorial]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Conference-1]] [[Has conference type::Presentation||Tutorial]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Conference-1#0##"
+ ],
+ "count": "1",
+ "dataitems": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "<q>[[Conference-1]] [[Has conference type::Presentation||Tutorial||Another]]</q> OR [[Has conference type::Presentation||Tutorial||Another]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "results": [
+ "Conference-1#0##",
+ "Conference-2#0##"
+ ],
+ "count": "2",
+ "dataitems": []
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_HELP": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0903.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0903.json
new file mode 100644
index 00000000..32eb8c64
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0903.json
@@ -0,0 +1,347 @@
+{
+ "description": "Test `_wpg`/`_num`/`_txt` for disjunction OR || (T31866, #1059, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/Q0903/Number/1",
+ "contents": "[[Has number::1]]"
+ },
+ {
+ "page": "Example/Q0903/Number/2",
+ "contents": "[[Has number::2]]"
+ },
+ {
+ "page": "Example/Q0903/Number/3",
+ "contents": "[[Has number::3]]"
+ },
+ {
+ "page": "Example/Q0903/Title/1",
+ "contents": "[[Has text::Foo]] [[Has page::123]]"
+ },
+ {
+ "page": "Example/Q0903/Title/2",
+ "contents": "[[Has text::Foobar]] [[Has page::ABC]]"
+ },
+ {
+ "page": "Example/Q0903/Title/3",
+ "contents": "[[Has text::FOO]] [[Has page::abc]]"
+ },
+ {
+ "page": "Example/Q0903/Title/4",
+ "contents": "[[Has text::FoO]] [[Has page::aBc]]"
+ },
+ {
+ "page": "Example/Q0903/Title/5",
+ "contents": "[[Has text::FoO]] [[Has page::Example/Q0903/Title/2]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has number::1]] OR [[Has number::2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0903/Number/1#0##",
+ "Example/Q0903/Number/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 same as #0",
+ "condition": "[[Has number::1||2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0903/Number/1#0##",
+ "Example/Q0903/Number/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Has text::~Foo*]][[Has page::123||ABC]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0903/Title/1#0##",
+ "Example/Q0903/Title/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 same as #2",
+ "condition": "[[Has page::123||ABC]][[Has text::~Foo*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0903/Title/1#0##",
+ "Example/Q0903/Title/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 same as #2",
+ "condition": "[[Has text::~Foo*]][[Has page::123]] OR [[Has page::ABC]][[Has text::~Foo*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0903/Title/1#0##",
+ "Example/Q0903/Title/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "skip-on": {
+ "elastic" : "Finds 5 due to `oo`, `OO`, and `oO` being matched using an analyzed field"
+ },
+ "condition": "[[Has text::+]][[Has text::~*oo*||~*OO*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0903/Title/1#0##",
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5.elastic",
+ "skip-on": {
+ "elastic" : [ "not", "Only relevant to ES (see #5 comment)" ]
+ },
+ "condition": "[[Has text::+]][[Has text::~*oo*||~*OO*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 5,
+ "results": [
+ "Example/Q0903/Title/1#0##",
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##",
+ "Example/Q0903/Title/4#0##",
+ "Example/Q0903/Title/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 same as #5",
+ "skip-on": {
+ "elastic" : "Finds 5 due to `oo`, `OO`, and `oO` being matched using an analyzed field"
+ },
+ "condition": "[[Has text::+]][[Has text::~*OO*||~*oo*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0903/Title/1#0##",
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6.elastic",
+ "skip-on": {
+ "elastic" : [ "not", "Only relevant to ES (see #6 comment)" ]
+ },
+ "condition": "[[Has text::+]][[Has text::~*OO*||~*oo*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 5,
+ "results": [
+ "Example/Q0903/Title/1#0##",
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##",
+ "Example/Q0903/Title/4#0##",
+ "Example/Q0903/Title/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7",
+ "condition": "[[Has page::+]][[Has page::~*a*||~*A*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##",
+ "Example/Q0903/Title/4#0##",
+ "Example/Q0903/Title/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8",
+ "skip-on": {
+ "elastic" : "Finds 3 due to `b` and `B` being matched using an analyzed field"
+ },
+ "condition": "[[Has page::+]][[Has page::~*B*]][[Has text::~*OO*||~*oo*||~*oO*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8.elastic",
+ "skip-on": {
+ "elastic" : [ "not", "Only relevant to ES (see #8 comment)" ]
+ },
+ "condition": "[[Has page::+]][[Has page::~*B*]][[Has text::~*OO*||~*oo*||~*oO*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##",
+ "Example/Q0903/Title/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9",
+ "skip-on": {
+ "elastic" : "Finds 4 due to `bc`, `Bc`, and `BC` being matched using an analyzed field"
+ },
+ "condition": "[[Has text::~*oO*]][[Has page::~*Bc*|| <q>[[Has page::~*a*||~*A*]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0903/Title/4#0##",
+ "Example/Q0903/Title/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9.elastic",
+ "skip-on": {
+ "elastic" : [ "not", "Only relevant to ES (see #9 comment)" ]
+ },
+ "condition": "[[Has text::~*oO*]][[Has page::~*Bc*|| <q>[[Has page::~*a*||~*A*]]</q>]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##",
+ "Example/Q0903/Title/4#0##",
+ "Example/Q0903/Title/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10, see issue #19",
+ "condition": "[[Has page::~*b*||~*B*]] AND [[Has text::~*oO*||~*OO*||~*oo*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q0903/Title/2#0##",
+ "Example/Q0903/Title/3#0##",
+ "Example/Q0903/Title/4#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0904.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0904.json
new file mode 100644
index 00000000..649f739a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0904.json
@@ -0,0 +1,142 @@
+{
+ "description": "Test `_wpg`/`_txt` disjunction in connection with property hierarchies (#1060, en, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page-0",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page-1",
+ "contents": "[[Has type::Page]] [[Subproperty of::Has page-0]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page-2",
+ "contents": "[[Has type::Page]] [[Subproperty of::Has page-0]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text-1",
+ "contents": "[[Has type::Text]] [[Subproperty of::Has text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text-2",
+ "contents": "[[Has type::Text]] [[Subproperty of::Has text]]"
+ },
+ {
+ "page": "Sample/1/1",
+ "contents": "[[Has text-1::Value 1]] [[Has page-1::Value 1]]"
+ },
+ {
+ "page": "Sample/1/2",
+ "contents": "[[Has text-2::Value 1]] [[Has page-2::Value 1]]"
+ },
+ {
+ "page": "Sample/2/1",
+ "contents": "[[Has text-1::Value 2]] [[Has page-1::Value 2]]"
+ },
+ {
+ "page": "Sample/2/2",
+ "contents": "[[Has text-2::Value 2]] [[Has page-2::Value 2]]"
+ },
+ {
+ "page": "Sample/2/3",
+ "contents": "[[Has text-2::Value 3]] [[Has page-2::Value 3]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Has text-1::Value 1||Value 2]] AND [[Has page-0::Value 1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Sample/1/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has text-1::Value 1||Value 2]] AND [[Has page-0::Value 1||Value 2]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Sample/1/1#0##",
+ "Sample/2/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 equivalent to #1",
+ "condition": "<q>[[Has text-1::Value 1]] OR [[Has text-1::Value 2]]</q> AND <q>[[Has page-0::Value 1]] OR [[Has page-0::Value 2]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Sample/1/1#0##",
+ "Sample/2/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "<q>[[Has text-1::~*1*||~*2*]] OR [[Has text-2::Value 3]]</q> AND [[Has page-0::Value 1||Value 3]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Sample/1/1#0##",
+ "Sample/2/3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgQSubpropertyDepth": 10,
+ "smwgQSubcategoryDepth": 10,
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/property hierarchies are currently not implemented"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0905.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0905.json
new file mode 100644
index 00000000..8a0ef940
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0905.json
@@ -0,0 +1,209 @@
+{
+ "description": "Test `_wpg`/`_txt` conjunction queries (#1362, #1060)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/Q0905/1",
+ "contents": "[[Category:Q0905]] [[Has page::123]] [[Has page::ABC]] [[Has text::123]] [[Has text::ABC]]"
+ },
+ {
+ "page": "Example/Q0905/2",
+ "contents": "[[Category:Q0905]] [[Has page::1234]] [[Has page::ABCD]] [[Has text::1234]] [[Has text::ABCD]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Category:Q0905]] [[Has page::123]] [[Has page::!ABCD]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0905/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Category:Q0905]] [[Has page::123]] [[Has page::ABCD]] [[Example/Q0905/1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 regression case",
+ "condition": "[[Example/Q0905/1]] [[Has page::123]] [[Has page::ABCD]] [[Category:Q0905]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Category:Q0905]] [[Has page::123]] [[Has text::ABCD]] [[Example/Q0905/1]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 regression case",
+ "condition": "[[Example/Q0905/1]] [[Has page::123]] [[Has text::ABCD]] [[Category:Q0905]] ",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5, C AND (A OR B)",
+ "condition": "[[Category:Q0905]] [[!Example/Q0905/1]] <q>[[Has page::123]] OR [[Has page::!ABCD]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0905/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6, (A OR B) AND C",
+ "condition": "<q>[[Has page::123]] OR [[Has page::!ABCD]]</q> [[!Example/Q0905/1]] [[Category:Q0905]] ",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0905/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7, (A OR B) AND (C OR D)",
+ "condition": "[[Category:Q0905]] <q>[[Has page::123]] OR [[Has text::1234]]</q> <q>[[Has page::ABCD]] OR [[Has text::ABC]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0905/1#0##",
+ "Example/Q0905/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8, (A OR B) AND (C OR D) AND E",
+ "condition": "[[Category:Q0905]] <q>[[Has page::123]] OR [[Has text::1234]]</q> <q>[[Has page::ABCD]] OR [[Has text::ABC]]</q> [[Has page::123]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0905/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9, E AND (A OR B) AND (C OR D)",
+ "condition": "[[Category:Q0905]] [[Has page::123]] <q>[[Has page::123]] OR [[Has text::1234]]</q> <q>[[Has page::ABCD]] OR [[Has text::ABC]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0905/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10, (A OR B) AND (C OR D) AND !E AND F",
+ "condition": "<q>[[Has page::123]] OR [[Has page::ABCD]]</q><q>[[Has page::1234]] OR [[Has page::ABC]]</q>[[Has page::!123]][[Has page::ABCD]][[Category:Q0905]] ",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0905/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10, !E AND F AND (A OR B) AND (C OR D)",
+ "condition": "[[Category:Q0905]] [[Has page::!123]][[Has page::ABCD]]<q>[[Has page::123]] OR [[Has page::ABCD]]</q><q>[[Has page::1234]] OR [[Has page::ABC]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0905/2#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0906.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0906.json
new file mode 100644
index 00000000..5d218b48
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0906.json
@@ -0,0 +1,163 @@
+{
+ "description": "Test `_wpg`/`_txt` with enabled `SMW_FIELDT_CHAR_NOCASE` (#1912, `smwgFieldTypeFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/Q0906/1",
+ "contents": "[[Category:Q0906]] [[Has page::noCASE]] [[Has text::noCASE]]"
+ },
+ {
+ "page": "Example/Q0906/2",
+ "contents": "[[Category:Q0906]] [[Has page::NOcase]] [[Has text::NOcase]]"
+ },
+ {
+ "page": "Example/Q0906/3",
+ "contents": "[[Category:Q0906]] [[Has page::NOoNcase]] [[Has text::NOoNcase]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (on _wpg type ~ match)",
+ "condition": "[[Category:Q0906]] [[Has page::~*noCa*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0906/1#0##",
+ "Example/Q0906/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (on _txt type as ~ match)",
+ "condition": "[[Category:Q0906]] [[Has text::~*NOcA*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0906/1#0##",
+ "Example/Q0906/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (on _wpg type !~ match)",
+ "condition": "[[Category:Q0906]] [[Has page::!~*noCa*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0906/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (on _txt type as !~ match)",
+ "condition": "[[Category:Q0906]] [[Has text::!~*NOcA*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0906/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "skip-on": {
+ "virtuoso": "Not suported",
+ "sesame": "Not suported",
+ "fuseki": "Not suported",
+ "blazegraph": "Not suported"
+ },
+ "about": "#4 (on _txt type as object match)",
+ "condition": "[[Category:Q0906]] [[Has text::nocase]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0906/1#0##",
+ "Example/Q0906/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "skip-on": {
+ "virtuoso": "Not suported",
+ "sesame": "Not suported",
+ "fuseki": "Not suported",
+ "blazegraph": "Not suported"
+ },
+ "about": "#5 (on _txt type as !object match)",
+ "condition": "[[Category:Q0906]] [[Has text::!nocase]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0906/3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_NOCASE"
+ ],
+ "smwgFieldTypeFeatures": [
+ "SMW_FIELDT_CHAR_NOCASE"
+ ],
+ "smwgElasticsearchConfig" : {
+ "connection":{
+ "retries": 1
+ },
+ "query": {
+ "text.field.case.insensitive.eq.match": true
+ }
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "PostgreSQL requires \"citext\" otherwise it returns with \"Error: 42704 ERROR: type \"citext\" does not exist\"",
+ "sqlite": "NOCASE is not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0907.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0907.json
new file mode 100644
index 00000000..4b845b35
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0907.json
@@ -0,0 +1,111 @@
+{
+ "description": "Test `_txt`/`_uri` with enabled `SMW_FIELDT_CHAR_LONG | SMW_FIELDT_CHAR_NOCASE` (#1912, #2499, `smwgFieldTypeFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/Q0907/1",
+ "contents": {
+ "import-from": "/../Fixtures/q-0907-1.txt"
+ }
+ },
+ {
+ "page": "Example/Q0907/2",
+ "contents": {
+ "import-from": "/../Fixtures/q-0907-2.txt"
+ }
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (on _txt within 300 char range)",
+ "condition": "[[Category:Q0907]] [[Has text::~*libero*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0907/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (on _txt within 300 char range, case insensitive)",
+ "condition": "[[Category:Q0907]] [[Has text::~*LIbero*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0907/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (on _uri within 300 char range)",
+ "condition": "[[Category:Q0907]] [[Has url::~*stack*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0907/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (on _uri within 300 char range)",
+ "condition": "[[Category:Q0907]] [[Has url::~*STACK*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0907/2#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_NOCASE"
+ ],
+ "smwgFieldTypeFeatures": [
+ "SMW_FIELDT_CHAR_NOCASE",
+ "SMW_FIELDT_CHAR_LONG"
+ ]
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "PostgreSQL requires \"citext\" otherwise it returns with \"Error: 42704 ERROR: type \"citext\" does not exist\"",
+ "sqlite": "NOCASE is not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0908.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0908.json
new file mode 100644
index 00000000..3632002f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0908.json
@@ -0,0 +1,219 @@
+{
+ "description": "Test `_wpg`/`_txt`/`_uri` on enabled `SMW_FIELDT_CHAR_LONG | SMW_FIELDT_CHAR_NOCASE` with `like:/nlike:` (#1912, #2499, `smwgFieldTypeFeatures`, `smwgSparqlQFeatures`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/Q0908/0",
+ "contents": "[[Category:Q0908]] [[Has page::Some title]] [[Has text::Some title]] [[Has url::http://example.org/some title]] {{#subobject: |Has page=SOME title |Has text=SOME title |Has url=http://example.org/SOME title |@category=Q0908 }}"
+ },
+ {
+ "page": "Example/Q0908/1",
+ "contents": "[[Category:Q0908]] [[Has page::Some title WiTH a VaLUE]] {{#subobject: |Has page=SOME title WITH A value |@category=Q0908 }}"
+ },
+ {
+ "page": "Example/Q0908/2",
+ "contents": "[[Category:Q0908]] [[Has text::Some title WiTH a VaLUE]] {{#subobject: |Has text=SOME title WITH A value |@category=Q0908 }}"
+ },
+ {
+ "page": "Example/Q0908/3",
+ "contents": "[[Category:Q0908]] [[Has url::http://example.org/Some title WiTH a VaLUE]] {{#subobject: |Has url=http://example.org/SOME title WITH A value |@category=Q0908 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (on _wpg, like:)",
+ "condition": "[[Category:Q0908]] [[Has page::like:some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/1#0##",
+ "Example/Q0908/1#0##_fddfd44d1be8e8a7f3ea5f4893df9963"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (on _wpg, nlike:)",
+ "condition": "[[Category:Q0908]] [[Has page::nlike:some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/0#0##",
+ "Example/Q0908/0#0##_34013e9e1a62a2138034ac5287a7cf0e"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (on _txt, equal)",
+ "condition": "[[Category:Q0908]] [[Has text::some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/2#0##",
+ "Example/Q0908/2#0##_52d6bd41c1e8946f754f9687b88ded4c"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (on _txt, like:)",
+ "condition": "[[Category:Q0908]] [[Has text::like:some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/2#0##",
+ "Example/Q0908/2#0##_52d6bd41c1e8946f754f9687b88ded4c"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 (on _txt, nlike:)",
+ "condition": "[[Category:Q0908]] [[Has text::nlike:some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/0#0##",
+ "Example/Q0908/0#0##_34013e9e1a62a2138034ac5287a7cf0e"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 (on _uri, equal)",
+ "skip-on": {
+ "fuseki": "Using lcase on _uri/equal is not supported",
+ "sesame": "Using lcase on _uri/equal is not supported",
+ "blazegraph": "Using lcase on _uri/equal is not supported",
+ "virtuoso": "Using lcase on _uri/equal is not supported"
+ },
+ "condition": "[[Category:Q0908]] [[Has url::http://example.org/some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/3#0##",
+ "Example/Q0908/3#0##_bc98426861e347260e7aa56265803598"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 (on _uri, like:)",
+ "condition": "[[Category:Q0908]] [[Has url::like:http://example.org/some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/3#0##",
+ "Example/Q0908/3#0##_bc98426861e347260e7aa56265803598"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 (on _uri, nlike:)",
+ "condition": "[[Category:Q0908]] [[Has url::nlike:http://example.org/some title with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/0#0##",
+ "Example/Q0908/0#0##_34013e9e1a62a2138034ac5287a7cf0e"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8 (on _uri, in:)",
+ "condition": "[[Category:Q0908]] [[Has url::in:with a value]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q0908/3#0#",
+ "Example/Q0908/3#0##_bc98426861e347260e7aa56265803598"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_NOCASE"
+ ],
+ "smwgFieldTypeFeatures": [
+ "SMW_FIELDT_CHAR_NOCASE",
+ "SMW_FIELDT_CHAR_LONG"
+ ],
+ "smwgElasticsearchConfig" : {
+ "connection":{
+ "retries": 1
+ },
+ "query": {
+ "uri.field.case.insensitive": true,
+ "text.field.case.insensitive.eq.match": true
+ }
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "postgres": "PostgreSQL requires \"citext\" otherwise it returns with \"Error: 42704 ERROR: type \"citext\" does not exist\"",
+ "sqlite": "NOCASE is not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0909.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0909.json
new file mode 100644
index 00000000..7a21d237
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0909.json
@@ -0,0 +1,180 @@
+{
+ "description": "Test `_txt/`_uri`/`_num`/`_dat` with `!...` (NEQ)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/Q0909/1",
+ "contents": "[[Has text::Foo/Bar]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/2",
+ "contents": "[[Has text::Foo/Foobar]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/3",
+ "contents": "[[Has url::http://example.org/Foo/Bar]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/4",
+ "contents": "[[Has url::http://example.org/Foo/Foobar]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/5",
+ "contents": "[[Has number::123]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/6",
+ "contents": "[[Has number::456]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/7",
+ "contents": "[[Has date::1 Jan 1970 12:00]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/8",
+ "contents": "[[Has date::1 Jan 1970 12:01]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/9",
+ "contents": "[[Has page::123]] [[Category:Q0909]]"
+ },
+ {
+ "page": "Example/Q0909/10",
+ "contents": "[[Has page::456]] [[Category:Q0909]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Category:Q0909]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 10,
+ "results": [
+ "Example/Q0909/1#0##",
+ "Example/Q0909/2#0##",
+ "Example/Q0909/3#0##",
+ "Example/Q0909/4#0##",
+ "Example/Q0909/5#0##",
+ "Example/Q0909/6#0##",
+ "Example/Q0909/7#0##",
+ "Example/Q0909/8#0##",
+ "Example/Q0909/9#0##",
+ "Example/Q0909/10#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (! on text)",
+ "condition": "[[Category:Q0909]] [[Has text::+]] [[Has text::!Foo/Bar]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0909/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (! on uri)",
+ "condition": "[[Category:Q0909]] [[Has url::+]] [[Has url::!http://example.org/Foo/Bar]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0909/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (! on number)",
+ "condition": "[[Category:Q0909]] [[Has number::+]] [[Has number::!123]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0909/6#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 (! on date)",
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.+ doesn't support this!"
+ },
+ "condition": "[[Category:Q0909]] [[Has date::+]] [[Has date::!1 Jan 1970 12:00]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0909/8#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 (! on page)",
+ "condition": "[[Category:Q0909]] [[Has page::+]] [[Has page::!123]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q0909/10#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0910.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0910.json
new file mode 100644
index 00000000..2d5e04ee
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0910.json
@@ -0,0 +1,113 @@
+{
+ "description": "Test `SMW_QSORT_UNCONDITIONAL` (`smwgQSortFeatures`, skip-on all SPARQL repositories, postgres)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Q0910/1",
+ "contents": "[[Has page::123]] [[Category:Q0910]]"
+ },
+ {
+ "page": "Q0910/2",
+ "contents": "[[Has text::ABC]] [[Category:Q0910]]"
+ },
+ {
+ "page": "Q0910/3",
+ "contents": "[[Has text::345]] [[Category:Q0910]]"
+ },
+ {
+ "page": "Q0910/Q.1",
+ "contents": "{{#ask: [[Category:Q0910]] |?Has page |?Has text |sort=Has page,Has text |order=desc, desc }}"
+ },
+ {
+ "page": "Q0910/Q.2",
+ "contents": "{{#ask: [[Category:Q0910]] |?Has page |?Has text |sort=Has page,Has text |order=desc, asc }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (SMW_QSORT_UNCONDITIONAL display, 2, 3)",
+ "condition": "[[Category:Q0910]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10",
+ "sort": {
+ "Has_page" : "DESC"
+ }
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q0910/1#0##",
+ "Q0910/2#0##",
+ "Q0910/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#1 (SMW_QSORT_UNCONDITIONAL on Has page=desc, Has text=desc)",
+ "skip-on": {
+ "postgres": "Has different order than MySQL/SQLite, needs investigation."
+ },
+ "subject": "Q0910/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"Q0910/1\">Q0910/1</a></td><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=.* title=\"Q0910/2\">Q0910/2</a></td><td class=\"Has-page smwtype_wpg\"></td><td class=\"Has-text smwtype_txt\">ABC</td>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"Q0910/3\">Q0910/3</a></td><td class=\"Has-page smwtype_wpg\"></td><td class=\"Has-text smwtype_txt\" data-sort-value=\"345\">345</td>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#2 (SMW_QSORT_UNCONDITIONAL on Has page=desc, Has text=asc)",
+ "skip-on": {
+ "postgres": "Has different order than MySQL/SQLite, needs investigation."
+ },
+ "subject": "Q0910/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"Q0910/1\">Q0910/1</a></td><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<tr data-row-number=\"2\" class=\"row-even\"><td class=\"smwtype_wpg\"><a href=.* title=\"Q0910/3\">Q0910/3</a></td><td class=\"Has-page smwtype_wpg\"></td><td class=\"Has-text smwtype_txt\" data-sort-value=\"345\">345</td>",
+ "<tr data-row-number=\"3\" class=\"row-odd\"><td class=\"smwtype_wpg\"><a href=.* title=\"Q0910/2\">Q0910/2</a></td><td class=\"Has-page smwtype_wpg\"></td><td class=\"Has-text smwtype_txt\">ABC</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgQSortFeatures": [
+ "SMW_QSORT",
+ "SMW_QSORT_UNCONDITIONAL"
+ ],
+ "smwgElasticsearchConfig": {
+ "query": {
+ "sort.property.must.exists": false
+ }
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "SMW_QSORT_UNCONDITIONAL isn't implemented",
+ "sesame": "SMW_QSORT_UNCONDITIONAL isn't implemented",
+ "fuseki": "SMW_QSORT_UNCONDITIONAL isn't implemented",
+ "blazegraph": "SMW_QSORT_UNCONDITIONAL isn't implemented"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0911.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0911.json
new file mode 100644
index 00000000..f46b9c7f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-0911.json
@@ -0,0 +1,54 @@
+{
+ "description": "Test `_wpg` empty chain/subquery (AND, OR)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q0911/1",
+ "contents": "[[Has page::Q0911]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (OR)",
+ "condition": "[[Has page::Q0911]] OR [[Some page.Another page::Foo]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q0911/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (AND)",
+ "condition": "[[Has page::Q0911]] [[Some page.Another page::Foo]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1002.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1002.json
new file mode 100644
index 00000000..7bfa5183
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1002.json
@@ -0,0 +1,167 @@
+{
+ "description": "Test `_dat` range for non strict comparators (#285, `smwStrictComparators=false`, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/1002/10-Jan",
+ "contents": "[[Category:Date range]] [[Has date::10 Jan 1970]]"
+ },
+ {
+ "page": "Example/1002/12-Jan",
+ "contents": "[[Category:Date range]] [[Has date::12 Jan 1970]]"
+ },
+ {
+ "page": "Example/1002/20-Jan",
+ "contents": "[[Category:Date range]] [[Has date::20 Jan 1970]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 greater than, equal to (non strict)",
+ "condition": "[[Category:Date range]] [[Has date::>10 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1002/10-Jan#0##",
+ "Example/1002/12-Jan#0##",
+ "Example/1002/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 greater than, equal to",
+ "condition": "[[Category:Date range]] [[Has date::≥10 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1002/10-Jan#0##",
+ "Example/1002/12-Jan#0##",
+ "Example/1002/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 greater than",
+ "condition": "[[Category:Date range]] [[Has date::>>10 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1002/12-Jan#0##",
+ "Example/1002/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Category:Date range]] [[Has date::>11 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1002/12-Jan#0##",
+ "Example/1002/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 smaller than, equal to (non strict)",
+ "condition": "[[Category:Date range]] [[Has date::<20 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1002/10-Jan#0##",
+ "Example/1002/12-Jan#0##",
+ "Example/1002/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 smaller than, equal to",
+ "condition": "[[Category:Date range]] [[Has date::≤20 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1002/10-Jan#0##",
+ "Example/1002/12-Jan#0##",
+ "Example/1002/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 smaller than",
+ "condition": "[[Category:Date range]] [[Has date::<<20 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1002/10-Jan#0##",
+ "Example/1002/12-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7",
+ "condition": "[[Category:Date range]] [[Has date::<19 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1002/10-Jan#0##",
+ "Example/1002/12-Jan#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 rdfs / subproperty/subcategory hierarchies are not supported"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1003.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1003.json
new file mode 100644
index 00000000..861760aa
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1003.json
@@ -0,0 +1,165 @@
+{
+ "description": "Test `_dat` range for strict comparators (#285, `smwStrictComparators=true`, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/1003/10-Jan",
+ "contents": "[[Category:Date range]] [[Has date::10 Jan 1970]]"
+ },
+ {
+ "page": "Example/1003/12-Jan",
+ "contents": "[[Category:Date range]] [[Has date::12 Jan 1970]]"
+ },
+ {
+ "page": "Example/1003/20-Jan",
+ "contents": "[[Category:Date range]] [[Has date::20 Jan 1970]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 greater than",
+ "condition": "[[Category:Date range]] [[Has date::>10 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1003/12-Jan#0##",
+ "Example/1003/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 greater than",
+ "condition": "[[Category:Date range]] [[Has date::>>10 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1003/12-Jan#0##",
+ "Example/1003/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 greater than, equal to",
+ "condition": "[[Category:Date range]] [[Has date::≥10 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1003/10-Jan#0##",
+ "Example/1003/12-Jan#0##",
+ "Example/1003/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Category:Date range]] [[Has date::>11 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1003/12-Jan#0##",
+ "Example/1003/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 smaller than",
+ "condition": "[[Category:Date range]] [[Has date::<20 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1003/10-Jan#0##",
+ "Example/1003/12-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 smaller than",
+ "condition": "[[Category:Date range]] [[Has date::<<20 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1003/10-Jan#0##",
+ "Example/1003/12-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 smaller than, equal to",
+ "condition": "[[Category:Date range]] [[Has date::≤20 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1003/10-Jan#0##",
+ "Example/1003/12-Jan#0##",
+ "Example/1003/20-Jan#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7",
+ "condition": "[[Category:Date range]] [[Has date::<19 Jan 1970]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1003/10-Jan#0##",
+ "Example/1003/12-Jan#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": true
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 somwhow fails for >/>>"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1004.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1004.json
new file mode 100644
index 00000000..22634725
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1004.json
@@ -0,0 +1,175 @@
+{
+ "description": "Test `_dat` range for `~`/`!~` comparators (#1178, `smwStrictComparators=false`, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/1004/15-Jun",
+ "contents": "{{#subobject:|@category=E-1004|Has date=15 Jun 2011 17:59:59}}{{#subobject:|@category=E-1004|Has date=15 Jun 2011 18:53}}{{#subobject:|@category=E-1004|Has date=15 Jun 2011 18:43}}{{#subobject:|@category=E-1004|Has date=15 Jun 2011 19:53}}"
+ },
+ {
+ "page": "Example/1004/16-Jun",
+ "contents": "{{#subobject:|@category=E-1004|Has date=16 Jul 2011 19:53}}"
+ },
+ {
+ "page": "Example/1004/17-Jun",
+ "contents": "{{#subobject:|@category=E-1004|Has date=17 Jun 2011 19:53:05}}{{#subobject:|@category=E-1004|Has date=17 Jun 2011 19:53:15}}{{#subobject:|@category=E-1004|Has date=17 Jun 2011 19:53:07}}{{#subobject:|@category=E-1004|Has date=17 Jun 2011 19:54:07}}"
+ },
+ {
+ "page": "Example/1004/17-Jun-1356",
+ "contents": "{{#subobject:|@category=E-1004|Has date=17 Jun 1356 19:53:05}}{{#subobject:|@category=E-1004|Has date=17 Jun 1356 19:53:15}}{{#subobject:|@category=E-1004|Has date=17 Jun 1356 19:53:07}}{{#subobject:|@category=E-1004|Has date=17 Jun 1356 19:54:07}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 for the same hour",
+ "condition": "[[Category:E-1004]] [[Has date::~15 Jun 2011 18:00]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1004/15-Jun#0##_3ac75bf67c06e184b53c2fe47dc9838f",
+ "Example/1004/15-Jun#0##_25fd2aa8d8bc9c7fe64f1161beb1e53e"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 for the same day",
+ "condition": "[[Category:E-1004]] [[Has date::~15 Jun 2011]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/1004/15-Jun#0##_3ac75bf67c06e184b53c2fe47dc9838f",
+ "Example/1004/15-Jun#0##_25fd2aa8d8bc9c7fe64f1161beb1e53e",
+ "Example/1004/15-Jun#0##_42f6ee5000aee48058fef6e89d988122",
+ "Example/1004/15-Jun#0##_93e03330595abc209f006bd389af97ca"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 for the same month",
+ "condition": "[[Category:E-1004]] [[Has date::~ Jun 2011]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 8,
+ "results": [
+ "Example/1004/15-Jun#0##_3ac75bf67c06e184b53c2fe47dc9838f",
+ "Example/1004/15-Jun#0##_25fd2aa8d8bc9c7fe64f1161beb1e53e",
+ "Example/1004/15-Jun#0##_42f6ee5000aee48058fef6e89d988122",
+ "Example/1004/15-Jun#0##_93e03330595abc209f006bd389af97ca",
+ "Example/1004/17-Jun#0##_546d85f0e65445d6ddebc327d82bc9b4",
+ "Example/1004/17-Jun#0##_d6ae457c1063eb3280a01617e331ae16",
+ "Example/1004/17-Jun#0##_97d8169c6bcb5357c7d4ed617de6b683",
+ "Example/1004/17-Jun#0##_2321a4ca8cce9a9f1200e7bcc6530b32"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 not for the same month",
+ "condition": "[[Category:E-1004]] [[Has date::~ 2011]] [[Has date::!~ Jun 2011]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1004/16-Jun#0##_c13e26365fd030c4505450df0da097ca"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 for the same minute",
+ "condition": "[[Category:E-1004]] [[Has date::~ 17 Jun 2011 19:53 ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1004/17-Jun#0##_546d85f0e65445d6ddebc327d82bc9b4",
+ "Example/1004/17-Jun#0##_d6ae457c1063eb3280a01617e331ae16",
+ "Example/1004/17-Jun#0##_97d8169c6bcb5357c7d4ed617de6b683"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 not for the same minute",
+ "condition": "[[Category:E-1004]] [[Has date::~ 17 Jun 2011 19:00]] [[Has date::!~ 17 Jun 2011 19:53]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1004/17-Jun#0##_2321a4ca8cce9a9f1200e7bcc6530b32"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 for the same sec",
+ "condition": "[[Category:E-1004]] [[Has date::~ 17 Jun 2011 19:53:05 ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1004/17-Jun#0##_546d85f0e65445d6ddebc327d82bc9b4"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 for the same year",
+ "condition": "[[Category:E-1004]] [[Has date::!~ 2011 ]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/1004/17-Jun-1356#0##_4034c283fdf86e4170912b3c85c970e8",
+ "Example/1004/17-Jun-1356#0##_c649d0effa6cd11dd6a4def82ac6523f",
+ "Example/1004/17-Jun-1356#0##_b080b00743a9e79d619f417b2268156f",
+ "Example/1004/17-Jun-1356#0##_af39ab3a77d159be5d8f2a1ddfc72d37"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 somwhow fails for >/>>"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1101.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1101.json
new file mode 100644
index 00000000..ed2a11fa
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1101.json
@@ -0,0 +1,189 @@
+{
+ "description": "Test _rec for non strict comparators queries (`smwStrictComparators=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has title",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has year",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has population",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km²]] [[Corresponds to::1000 m²]] [[Corresponds to::988.42153133973 rood]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Population density",
+ "contents": "[[Has type::Record]] [[Has fields::Has population;Has area]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Book record",
+ "contents": "[[Has type::Record]] [[Has fields::Has title;Has year]]"
+ },
+ {
+ "page": "Example/1101/City A",
+ "contents": "[[Category:Record example]] [[Population density::3900;1 km²]]"
+ },
+ {
+ "page": "Example/1101/City B",
+ "contents": "[[Category:Record example]] [[Population density::20169;1 km²]]"
+ },
+ {
+ "page": "Example/1101/Book A",
+ "contents": "[[Category:Record example]] [[Book record::Title with $&%'\\;* special characters ; 2001]]"
+ },
+ {
+ "page": "Example/1101/Book B",
+ "contents": "[[Category:Record example]] [[Book record::Book B; 2000]]"
+ },
+ {
+ "page": "Example/1101/Book C",
+ "contents": "[[Category:Record example]] [[Book record::Book C;30 Dec 2001]]"
+ },
+ {
+ "page": "Example/1101/Book D",
+ "contents": "[[Category:Record example]] [[Book record::Book D;1900]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 distinct value search",
+ "condition": "[[Category:Record example]] [[Population density::3900;1 km²]]",
+ "printouts": [
+ "Population density"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1101/City A#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Population_density",
+ "value": "3900;1 km²"
+ }
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1, T23926 RecordsToContainSpecialCharactersCausedByHtmlEncoding",
+ "condition": "[[Category:Record example]] [[Book record::Title with $&%'\\;* special characters ; 2001]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1101/Book A#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2, T36019 RecordToContainFieldComparator",
+ "condition": "[[Category:Record example]] [[Book record::?;<30 Dec 2001]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/1101/Book A#0##",
+ "Example/1101/Book B#0##",
+ "Example/1101/Book C#0##",
+ "Example/1101/Book D#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "condition": "[[Category:Record example]] [[Book record::?;<1901]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1101/Book D#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "condition": "[[Category:Record example]] [[Book record::?;>30 Dec 2001]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1101/Book C#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5",
+ "condition": "[[Category:Record example]] [[Book record::?;>1901]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1101/Book A#0##",
+ "Example/1101/Book B#0##",
+ "Example/1101/Book C#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6",
+ "condition": "[[Category:Record example]] [[Book record::?;!2001]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/1101/Book B#0##",
+ "Example/1101/Book C#0##",
+ "Example/1101/Book D#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1102.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1102.json
new file mode 100644
index 00000000..854b954a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1102.json
@@ -0,0 +1,95 @@
+{
+ "description": "Test `_rec` queries in combination with `_dat` `~/!~` search pattern (#1178, `smwStrictComparators=false`, skip virtuoso)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has status",
+ "contents": "[[Has type::Text]] [[Allows value::open]] [[Allows value::closed]] [[Allows value::in progress]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has status record",
+ "contents": "[[Has type::Record]] [[Has fields::Has date; Has status]]"
+ },
+ {
+ "page": "Example/1102/15-Dec-2007",
+ "contents": "{{#subobject:|@category=E-1102|Has status record=15 Dec 2007;closed}}{{#subobject:|@category=E-1102 |Has status record=15 Dec 2007;open}}"
+ },
+ {
+ "page": "Example/1102/16-Dec-2007",
+ "contents": "{{#subobject:|@category=E-1102 |Has status record=16 Dec 2007;closed}}"
+ },
+ {
+ "page": "Example/1102/345-BC",
+ "contents": "{{#subobject:|@category=E-1102|Has status record=345 BC;closed}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 disjunctive match for any status",
+ "condition": "[[Category:E-1102]] [[Has status record::~Dec 2007;?]] OR [[Has status record::~345 BC;?]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Example/1102/15-Dec-2007#0##_32971b257b2cfa9a364ae22e21ab4adf",
+ "Example/1102/15-Dec-2007#0##_a95f61c99770cf350f1388ae46e973bb",
+ "Example/1102/16-Dec-2007#0##_f1fd6537c6d2576390a45ba86e58ed5b",
+ "Example/1102/345-BC#0##_6f2d86633d90e76f0e9fa5e5d1fe6598"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 all closed in Dec 2007",
+ "condition": "[[Category:E-1102]] [[Has status record::~Dec 2007;closed]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1102/15-Dec-2007#0##_32971b257b2cfa9a364ae22e21ab4adf",
+ "Example/1102/16-Dec-2007#0##_f1fd6537c6d2576390a45ba86e58ed5b"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 all closed not at the 15 Dec 2007",
+ "condition": "[[Category:E-1102]] [[Has status record::!~ 15 Dec 2007;closed]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/1102/16-Dec-2007#0##_f1fd6537c6d2576390a45ba86e58ed5b",
+ "Example/1102/345-BC#0##_6f2d86633d90e76f0e9fa5e5d1fe6598"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false
+ },
+ "meta": {
+ "skip-on": {
+ "virtuoso": "Virtuoso 6.1 fails for BC"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1103.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1103.json
new file mode 100644
index 00000000..444ee226
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1103.json
@@ -0,0 +1,100 @@
+{
+ "description": "Test `_rec` using some additional search pattern (#1189, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "hasWeightMeasure",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 g, gram, grams]] [[Corresponds to::0.2 teaspoon, teaspoons]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "hasIngredient",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text number record",
+ "contents": "[[Has type::Record]] [[Has fields::Has text;Has number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "hasCookingIngredient",
+ "contents": "[[Has type::Record]] [[Has fields::hasIngredient;hasWeightMeasure]]"
+ },
+ {
+ "page": "Example/1103/1",
+ "contents": "[[Category:E-1103]][[Has text number record::SomeText;123]]"
+ },
+ {
+ "page": "Example/1103/2",
+ "contents": "[[Category:E-1103]][[hasCookingIngredient::salt:0.25 teaspoon]]"
+ },
+ {
+ "page": "Example/1103/3",
+ "contents": "{{#ask: [[Category:E-1103]][[hasCookingIngredient::salt;~teaspoon]] |?hasCookingIngredient}}"
+ },
+ {
+ "page": "Example/1103/4",
+ "contents": "[[Category:E-1103]][[Has text number record::SomeText;1234]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#1 verify no cached DataValue is invoked and causes wrong object deseralization (see #1189)",
+ "subject": "Example/1103/3",
+ "assert-output": {
+ "to-contain": [
+ "&quot;teaspoon&quot; is not a number"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#0 simple search that causes an error",
+ "condition": "[[Category:E-1103]] [[Has status record::SomeText;~12]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 0
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1, see issue #1207",
+ "condition": "[[Category:E-1103]] [[Has text number record::~*eT*;>123]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1103/4#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwStrictComparators": true
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1104.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1104.json
new file mode 100644
index 00000000..9391654f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1104.json
@@ -0,0 +1,86 @@
+{
+ "description": "Test `_rec` to find correct target for redirected property (#1244, en)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has status",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Project",
+ "contents": "[[Has type::Record]] [[Has fields::Has status;Has date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has project status",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has status",
+ "contents": "#REDIRECT [[Property:Has project status]]"
+ },
+ {
+ "page": "Example/1103/1",
+ "contents": "[[Category:Record redirect example]] [[Project::closed;15 Jan 1970]]"
+ },
+ {
+ "page": "Example/1103/2",
+ "contents": "{{#ask: [[Category:Record redirect example]] [[Project::closed;~1970]]|?Project=Status|+index=1|format=plainlist}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "format",
+ "about": "#0 indexed output",
+ "subject": "Example/1103/2",
+ "assert-output": {
+ "to-contain": [
+ "title=\"Property:Project\">Status</a>: closed"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Category:Record redirect example]] [[Project::closed;~1970]]",
+ "printouts": [
+ "Project"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/1103/1#0##"
+ ],
+ "datavalues": [
+ {
+ "property": "Project",
+ "value": "closed;15 Jan 1970"
+ }
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false,
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1105.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1105.json
new file mode 100644
index 00000000..33276325
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1105.json
@@ -0,0 +1,94 @@
+{
+ "description": "Test `_rec` in combination with named subobject (T49472, #1300, en, `smwStrictComparators=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record text",
+ "contents": "[[Has type::Record]] [[Has fields::Has text;Has number]]"
+ },
+ {
+ "page": "Example/Q1105/1",
+ "contents": "{{#subobject: Test|Has text=Foo|Has record text=abc;123}} {{#subobject: Test|Has text=Bar}}"
+ },
+ {
+ "page": "Example/Q1105/2",
+ "contents": "{{#subobject: Test|Has text=Bar}} {{#subobject: Test|Has text=Foo|Has record text=abc;456}}"
+ },
+ {
+ "page": "Example/Q1105/3",
+ "contents": "{{#subobject: Test|Has text=Foo|Has record text=def;456}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 declaration order does not matter (oppose to T49472)",
+ "condition": "[[Has record text::abc;?]]",
+ "printouts": [
+ "Has record text"
+ ],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q1105/1#0##Test",
+ "Example/Q1105/2#0##Test"
+ ],
+ "datavalues": [
+ {
+ "property": "Has record text",
+ "value": "abc;123"
+ },
+ {
+ "property": "Has record text",
+ "value": "abc;456"
+ }
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 same as #0 only to use property chain notation",
+ "condition": "[[Has record text.Has text::abc]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q1105/1#0##Test",
+ "Example/Q1105/2#0##Test"
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false,
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1106.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1106.json
new file mode 100644
index 00000000..0e1c0bdd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1106.json
@@ -0,0 +1,116 @@
+{
+ "description": "Test `_rec` with `~/!~` comparators on allowed values (#1207, `smwStrictComparators=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has restricted status record",
+ "contents": "[[Has type::Text]] [[Allows value::open]], [[Allows value::closed]], [[Allows value::in progress]]"
+ },
+ {
+ "page": "Example/Q1106/1",
+ "contents": "[[Category:E-Q1106]][[Has restricted status record::open]]"
+ },
+ {
+ "page": "Example/Q1106/2",
+ "contents": "[[Category:E-Q1106]]{{#set:Has restricted status record=closed}}"
+ },
+ {
+ "page": "Example/Q1106/3",
+ "contents": "{{#subobject:Has restricted status record=in progress|@category=E-Q1106}}"
+ },
+ {
+ "page": "Example/Q1106/4",
+ "contents": "[[Category:E-Q1106]][[Has restricted status record::none of the above]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 like *en*",
+ "condition": "[[Category:E-Q1106]][[Has restricted status record::~*en*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q1106/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 like cl*",
+ "condition": "[[Category:E-Q1106]][[Has restricted status record::~cl*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q1106/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 not like cl*",
+ "condition": "[[Category:E-Q1106]][[Has restricted status record::!~cl*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Example/Q1106/1#0##",
+ "Example/Q1106/3#0##_5005bc588cbc65273b9c8d9b96bf5c01"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 not like cl* AND *in*",
+ "condition": "[[Category:E-Q1106]]<q>[[Has restricted status record::!~cl*]] AND [[Has restricted status record::!~*in*]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q1106/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 not like cl* OR *in* (doesn't make much sense, we test it anyway)",
+ "condition": "[[Category:E-Q1106]]<q>[[Has restricted status record::!~cl*]] OR [[Has restricted status record::!~*in*]]</q>",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Example/Q1106/1#0##",
+ "Example/Q1106/2#0##",
+ "Example/Q1106/3#0##_5005bc588cbc65273b9c8d9b96bf5c01"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwStrictComparators": false,
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1107.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1107.json
new file mode 100644
index 00000000..5f2e6dce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1107.json
@@ -0,0 +1,84 @@
+{
+ "description": "Test `_rec`/`_mlt_rec`(`_PDESC`) to use property chaining (`wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]] [[Has property description::Text property@en]] [[Category:Q1107]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]] [[Has property description::Number property@en]] [[Category:Q1107]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has record text",
+ "contents": "[[Has type::Record]] [[Has fields::Has text;Has number]]"
+ },
+ {
+ "page": "Example/Q1107/1",
+ "contents": "{{#subobject: Test|Has text=Foo|Has record text=abc;222}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "condition": "[[Category:Q1107]] [[Has property description.Language code::en]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Has text#102##",
+ "Has number#102##"
+ ]
+ },
+ "store": {
+ "clear-cache": true
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "condition": "[[Has subobject.Has record text.Has number::222]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q1107/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Has record text.Has number::222]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q1107/1#0##Test"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1108.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1108.json
new file mode 100644
index 00000000..467c6d6e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1108.json
@@ -0,0 +1,106 @@
+{
+ "description": "Test conditions and constraint validations for allowed values `_LIST` and uniqueness `_PVUC` (#1207, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]] [[Allows value::open]], [[Allows value::closed]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has uniqueness",
+ "contents": "[[Has type::Text]] [[Has uniqueness constraint::true]]"
+ },
+ {
+ "page": "Example/Q1108/1",
+ "contents": "[[Category:Q1108]][[Has text::open]]"
+ },
+ {
+ "page": "Example/Q1108/2",
+ "contents": "[[Category:Q1108]][[Has text::close]]"
+ },
+ {
+ "page": "Example/Q1108/3",
+ "contents": "[[Category:Q1108]][[Has text::invalid]]"
+ },
+ {
+ "page": "Example/Q1108/4",
+ "contents": "[[Category:Q1108]] [[Has uniqueness::Foo]]"
+ },
+ {
+ "page": "Example/Q1108/5",
+ "contents": "[[Category:Q1108]] [[Has uniqueness::Foo]]"
+ },
+ {
+ "page": "Example/Q1108/Q1",
+ "contents": "{{#ask: [[Category:Q1108]] [[Has uniqueness::Foo]] |link=none}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#3 embedded query with uniqueness condition works without raising an issue due to different context page",
+ "subject": "Example/Q1108/Q1",
+ "assert-output": {
+ "to-contain": [
+ "Example/Q1108/4"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#0 matches one with open",
+ "condition": "[[Category:Q1108]][[Has text::open]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q1108/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 matches none",
+ "condition": "[[Category:Q1108]][[Has text::invalid]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "condition": "[[Category:Q1108]] [[Has uniqueness::Foo]]",
+ "printouts": [],
+ "parameters": {
+ "limit": 10
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Example/Q1108/4#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgDVFeatures": [
+ "SMW_DV_PVUC"
+ ],
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1200.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1200.json
new file mode 100644
index 00000000..4a7ae9cc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1200.json
@@ -0,0 +1,210 @@
+{
+ "description": "Test `_wpg/`_txt` with `~*` and `.../...` queries (ES only)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q1200/1/Foo bar/Bar",
+ "contents": "[[Category:Q1200]] [[Has text::Foo bar/Bar]] [[Has page::Foo bar/Bar]]"
+ },
+ {
+ "page": "Q1200/1/Foobar/Bar/Foo",
+ "contents": "[[Category:Q1200]] [[Has text::Foobar/Bar/Foo]] [[Has page::Foobar/Bar/Foo]]"
+ },
+ {
+ "page": "Q1200/1/Foo BAR/Foo",
+ "contents": "[[Category:Q1200]] [[Has text::Foo BAR/Foo]] [[Has page::Foo BAR/Foo]]"
+ },
+ {
+ "page": "Q1200/1/Foo/Bar",
+ "contents": "[[Category:Q1200]] [[Has text::Foo/Bar]] [[Has page::Foo/Bar]]"
+ },
+ {
+ "page": "Q1200/1/Foo",
+ "contents": "[[Category:Q1200]] [[Has text::Foo]] [[Has page::Foo]]"
+ },
+ {
+ "page": "Q1200/2",
+ "contents": "[[Category:Q1200]] {{#subobject: |Has page=Q1200/2 |Has text=Q1200/2 |Q1200/2=A,B,C|+sep=, }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (~*bar*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1200]] [[~*bar*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Q1200/1/Foo bar/Bar#0##",
+ "Q1200/1/Foobar/Bar/Foo#0##",
+ "Q1200/1/Foo BAR/Foo#0##",
+ "Q1200/1/Foo/Bar#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (~*Bar/*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1200]] [[~*Bar/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q1200/1/Foo bar/Bar#0##",
+ "Q1200/1/Foobar/Bar/Foo#0##",
+ "Q1200/1/Foo BAR/Foo#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (~*Foo bar/*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1200]] [[~*Foo bar/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1200/1/Foo bar/Bar#0##",
+ "Q1200/1/Foo BAR/Foo#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (~F??Bar/*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1200]] [[~*F??Bar/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1200/1/Foobar/Bar/Foo#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 (Has page:: ~*bar*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1200]] [[Has page::~*bar*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Q1200/1/Foo bar/Bar#0##",
+ "Q1200/1/Foobar/Bar/Foo#0##",
+ "Q1200/1/Foo BAR/Foo#0##",
+ "Q1200/1/Foo/Bar#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 (Has page::~*Bar/*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1200]] [[Has page::~*Bar/*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Q1200/1/Foo bar/Bar#0##",
+ "Q1200/1/Foobar/Bar/Foo#0##",
+ "Q1200/1/Foo BAR/Foo#0##",
+ "Q1200/1/Foo/Bar#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 (Has subobject::~*Q1200*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Has subobject::~*Q1200*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1200/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 (-Q1200/2.-Has subobject::~*Q1200*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[-Q1200/2.-Has subobject::~*Q1200*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "A#0##",
+ "B#0##",
+ "C#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1201.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1201.json
new file mode 100644
index 00000000..8f3803a4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1201.json
@@ -0,0 +1,114 @@
+{
+ "description": "Test `_wpg/`_txt` with `not:`/`!~` queries (ES only)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q1201/1",
+ "contents": "[[Category:Q1201]] [[Has text::Some text with foo]]"
+ },
+ {
+ "page": "Q1201/2",
+ "contents": "[[Category:Q1201]] [[Has text::Some text with foobar]]"
+ },
+ {
+ "page": "Q1201/3",
+ "contents": "[[Category:Q1201]] [[Has text::Some text with bar]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (not:foo)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1201]] [[not:foo]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1201/2#0##",
+ "Q1201/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (not:foo, not:bar)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1201]] [[not:foo]] [[not:bar]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1201/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (not:foo*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1201]] [[not:foo*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1201/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#0 (not:FOO)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1201]] [[not:FOO]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1201/2#0##",
+ "Q1201/3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1202.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1202.json
new file mode 100644
index 00000000..3e0d34f7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1202.json
@@ -0,0 +1,186 @@
+{
+ "description": "Test `_wpg/`_txt` with `not:`/`!~` queries (ES only, `raw.text`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q1202/1",
+ "contents": "[[Category:Q1202]] [[Has text::Some text with foo]]"
+ },
+ {
+ "page": "Q1202/2",
+ "contents": "[[Category:Q1202]] [[Has text::Some text with foobar]]"
+ },
+ {
+ "page": "Q1202/3",
+ "contents": "[[Category:Q1202]] [[Has text::Some text with bar]]"
+ },
+ {
+ "page": "Q1202/4",
+ "contents": "[[Category:Q1202]] free text without a foo property or value"
+ },
+ {
+ "page": "Q1202/5",
+ "contents": "[[Category:Q1202]] free text without a bar property or value"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (not:foo)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1202]] [[not:foo]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q1202/2#0##",
+ "Q1202/3#0##",
+ "Q1202/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (not:foo, not:bar)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1202]] [[not:foo]] [[not:bar]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1202/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (not:foo*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1202]] [[not:foo*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1202/3#0##",
+ "Q1202/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (not:FOO)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1202]] [[not:FOO]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q1202/2#0##",
+ "Q1202/3#0##",
+ "Q1202/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 (not:FOO*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1202]] [[not:FOO*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1202/3#0##",
+ "Q1202/5#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 (Has text::not:FOO)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1202]] [[Has text::not:FOO]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1202/2#0##",
+ "Q1202/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 (Has text::not:FOO*)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1202]] [[Has text::not:FOO*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1202/3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgElasticsearchConfig": {
+ "indexer": {
+ "raw.text": true
+ }
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1203.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1203.json
new file mode 100644
index 00000000..323f8eaf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1203.json
@@ -0,0 +1,271 @@
+{
+ "description": "Test `_wpg/`_txt` with `in:/phrase:` queries (ES only)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q1203/1",
+ "contents": "[[Category:Q1203]] [[Has text::fox]] [[Has page::fox]]"
+ },
+ {
+ "page": "Q1203/2",
+ "contents": "[[Category:Q1203]] [[Has text::fox and chicken both jump over ...]] [[Has page::fox and chicken both jump over ...]]"
+ },
+ {
+ "page": "Q1203/3",
+ "contents": "[[Category:Q1203]] [[Has text::fox jumps over ...]] [[Has page::fox jumps over ...]]"
+ },
+ {
+ "page": "Q1203/4",
+ "contents": "[[Category:Q1203]] [[Has text::fox-hunting is a sport ...]] [[Has page::fox-hunting is a sport ...]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0 (in:fox jump, match fox AND jump, see `minimum_should_match`)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[in:fox jump]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1203/2#0##",
+ "Q1203/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (Has text::in:fox jump, match fox AND jump)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has text::in:fox jump]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1203/2#0##",
+ "Q1203/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (Has page::in:fox jump, match fox AND jump)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has page::in:fox jump]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1203/2#0##",
+ "Q1203/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (in:fox)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Q1203/1#0##",
+ "Q1203/2#0##",
+ "Q1203/3#0##",
+ "Q1203/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 (Has text::in:fox)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has text::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Q1203/1#0##",
+ "Q1203/2#0##",
+ "Q1203/3#0##",
+ "Q1203/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 (Has page::in:fox)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has page::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Q1203/1#0##",
+ "Q1203/2#0##",
+ "Q1203/3#0##",
+ "Q1203/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 (phrase:fox jump, mind jump vs. jumps)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[phrase:fox jump]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count":0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#7 (Has text::phrase:fox jump, mind jump vs. jumps)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has text::phrase:fox jump]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count":0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#8 (Has page::phrase:fox jump, mind jump vs. jumps)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has page::phrase:fox jump]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count":0,
+ "results": []
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9 (phrase:fox jump*, `phrase_prefix`)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[phrase:fox jump*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1203/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#9 (Has text::phrase:fox jump*, `phrase_prefix`)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has text::phrase:fox jump*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1203/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#10 (Has page::phrase:fox jump*, `phrase_prefix`)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1203]] [[Has page::phrase:fox jump*]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1203/3#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgElasticsearchConfig": {
+ "indexer": {
+ "raw.text": false
+ }
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1204.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1204.json
new file mode 100644
index 00000000..cd6f6bad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1204.json
@@ -0,0 +1,204 @@
+{
+ "description": "Test `!` category queries (ES only, `smwgQSubcategoryDepth`)",
+ "setup": [
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q1204/1",
+ "contents": "[[Category:Q1204/0]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q1204/2",
+ "contents": "[[Category:Q1204/0]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q1204/1/1",
+ "contents": "[[Category:Q1204/1]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Q1204/2/1",
+ "contents": "[[Category:Q1204/2]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q1204/0",
+ "contents": "[[Category:Q1204/0]]"
+ },
+ {
+ "page": "Q1204/1",
+ "contents": "[[Category:Q1204/1]] [[Has page::fox]]"
+ },
+ {
+ "page": "Q1204/2",
+ "contents": "[[Category:Q1204/2]] [[Has page::fox and chicken both jump over ...]]"
+ },
+ {
+ "page": "Q1204/3",
+ "contents": "[[Category:Q1204/2]] [[Category:Q1204/1]] [[Has page::fox jumps over ...]]"
+ },
+ {
+ "page": "Q1204/4",
+ "contents": "[[Category:Q1204/2/1]] [[Category:Q1204/1/1]] [[Has page::fox-hunting is a sport ...]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "<q>[[Category:Q1204/1]] || [[Category:Q1204/2]] </q> [[Has page::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 4,
+ "results": [
+ "Q1204/1#0##",
+ "Q1204/2#0##",
+ "Q1204/3#0##",
+ "Q1204/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (!Q1204/1)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "<q>[[Category:!Q1204/1]] [[Category:Q1204/2]] </q> [[Has page::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1204/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (!Q1204/1|+depth=0)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "<q>[[Category:!Q1204/1|+depth=0] [[Category:Q1204/2]] </q> [[Has page::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1204/2#0##",
+ "Q1204/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (!Q1204/2)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "<q>[[Category:Q1204/1]] [[Category:!Q1204/2]] </q> [[Has page::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1204/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4 (!Q1204/2|+depth=0)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "<q>[[Category:Q1204/1]] [[Category:!Q1204/2|+depth=0]] </q> [[Has page::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1204/1#0##",
+ "Q1204/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#5 (Q1204/1 || !Q1204/2)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "<q>[[Category:Q1204/1]] || [[Category:!Q1204/2]] </q> [[Has page::in:fox]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q1204/1#0##",
+ "Q1204/3#0##",
+ "Q1204/4#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#6 (!Q1204/2)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Category:Q1204/0]] [[Category:!Q1204/2]] ",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1204/0#0##",
+ "Q1204/1#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgQSubcategoryDepth": 10,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgElasticsearchConfig": {
+ "indexer": {
+ "raw.text": false
+ }
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1205.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1205.json
new file mode 100644
index 00000000..ea54c467
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1205.json
@@ -0,0 +1,102 @@
+{
+ "description": "Test `[[Has subobject::!]]` / `[[Has subobject::!+]]` (ES only)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Q1205/1",
+ "contents": "[[Has page::Q1205]] {{#subobject: |Has page=Q1205/1}} {{#subobject: |Has page=Q1205/2}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Has page::in:Q1205]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q1205/1#0##",
+ "Q1205/1#0##_05d38f45f2ea3d1167f4c7c0d52f82d2",
+ "Q1205/1#0##_da6807dde88fa7a579fd5beed7b182cd"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (Has subobject::!, match entities with no subobject)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Has page::in:Q1205]][[Has subobject::!]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1205/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (Has subobject::+, those entities that poses a subobject)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Has page::in:Q1205]][[Has subobject::+]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1205/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3 (Has subobject::!+, those entities that don't poses a subobject)",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Has page::in:Q1205]][[Has subobject::!+]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1205/1#0##_05d38f45f2ea3d1167f4c7c0d52f82d2",
+ "Q1205/1#0##_da6807dde88fa7a579fd5beed7b182cd"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1206.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1206.json
new file mode 100644
index 00000000..14f04b23
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1206.json
@@ -0,0 +1,142 @@
+{
+ "description": "Test `cjk.best.effort.proximity.match` (ES only)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Q1206/1",
+ "contents": "[[Has page::æ±æ—¥æœ¬]] [[Has text::æ±æ—¥æœ¬]]"
+ },
+ {
+ "page": "Q1206/2",
+ "contents": "[[Has page::西日本]] [[Has text::西日本]]"
+ },
+ {
+ "page": "Q1206/3",
+ "contents": "[[Has text::。。。 暑ã•ãŒç¶šã„ã¦ã„る西日本ã¨æ±æ—¥æœ¬ã§ã¯ã€€ã€‚。。]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "query",
+ "about": "#0",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[Has page::in:西日本]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1206/2#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[in:西日本]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 3,
+ "results": [
+ "Q1206/2#0##",
+ "Q1206/3#0##",
+ "西日本#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[in:日本]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 5,
+ "results": [
+ "Q1206/1#0##",
+ "Q1206/2#0##",
+ "Q1206/3#0##",
+ "西日本#0##",
+ "æ±æ—¥æœ¬#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#3",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[in:æ±æ—¥æœ¬]] [[in:西日本]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1206/3#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#4",
+ "skip-on": {
+ "elastic": [ "not", "Only works with ES out of the box." ]
+ },
+ "condition": "[[in:æ±æ—¥æœ¬]] [[not:西日本]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 2,
+ "results": [
+ "Q1206/1#0##",
+ "æ±æ—¥æœ¬#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgElasticsearchConfig": {
+ "query": {
+ "cjk.best.effort.proximity.match": true
+ }
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1300.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1300.json
new file mode 100644
index 00000000..c48381dc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/q-1300.json
@@ -0,0 +1,80 @@
+{
+ "description": "Test `_geo` (requires Maps)",
+ "requires": {
+ "Maps": ">= 5.0"
+ },
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has coordinates",
+ "contents": "[[Has type::Geographic coordinate]]"
+ },
+ {
+ "page": "Q1300/1",
+ "contents": "[[Has coordinates::52°31'N, 13°24'E]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 ...",
+ "namespace": "SMW_NS_PROPERTY",
+ "subject": "Has coordinates",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_TYPE",
+ "_SKEY",
+ "_MDAT"
+ ],
+ "propertyValues": [
+ "http://semantic-mediawiki.org/swivt/1.0#_geo"
+ ]
+ }
+ }
+ },
+ {
+ "type": "query",
+ "about": "#1 (eq match)",
+ "condition": "[[Has coordinates::52°31'N, 13°24'E]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1300/1#0##"
+ ]
+ }
+ },
+ {
+ "type": "query",
+ "about": "#2 (distance match)",
+ "condition": "[[Has coordinates::52°31'N, 13°24'E (100km)]]",
+ "printouts": [],
+ "parameters": {
+ "limit": "10"
+ },
+ "assert-queryresult": {
+ "count": 1,
+ "results": [
+ "Q1300/1#0##"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0001.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0001.json
new file mode 100644
index 00000000..fc16ab4d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0001.json
@@ -0,0 +1,205 @@
+{
+ "description": "Test RDF output for `_txt`/`_wpg`/`_dat` (#881)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text property for rdf",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page property for rdf",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date property for rdf",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Rdf-1",
+ "contents": "[[Has page property for rdf::Test one]] [[Has text property for rdf::Test one]]"
+ },
+ {
+ "page": "Rdf-2",
+ "contents": "[[Has page property for rdf::Test two]] [[Has text property for rdf::Test two]]"
+ },
+ {
+ "page": "Rdf-3",
+ "contents": "{{#subobject:|Has page property for rdf=I--11--O|@sortkey=X99Y}} {{#subobject:Caractères spéciaux|Has text property for rdf={({[[&,,;-]]})} }}"
+ },
+ {
+ "page": "Rdf-4",
+ "contents": "[[Has date property for rdf::31/12/2014]] {{#subobject:|Has date property for rdf=1/1/1970}}"
+ },
+ {
+ "page": "Rdf-5",
+ "contents": "Not permitted to use [[Has subobject::foo]] {{DEFAULTSORT:AA-BB-CC}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 Single subject output",
+ "exportcontroller": {
+ "print-pages": [
+ "Rdf-1"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:Has_page_property_for_rdf rdf:resource=\"&wiki;Test_one\"/>",
+ "<property:Has_text_property_for_rdf rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Test one</property:Has_text_property_for_rdf>",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Rdf-1</swivt:wikiPageSortKey>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AHas_page_property_for_rdf\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AHas_text_property_for_rdf\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1",
+ "exportcontroller": {
+ "print-pages": [
+ "Rdf-1",
+ "Rdf-2"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D1\">",
+ "<rdfs:label>Rdf-1</rdfs:label>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D2\">",
+ "<rdfs:label>Rdf-2</rdfs:label>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2 Output for anonymous and named subobject",
+ "exportcontroller": {
+ "print-pages": [
+ "Rdf-3"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D3\">",
+ "<property:Has_subobject-23aux rdf:resource=\"&wiki;Rdf-2D3-23_c14ce3099ebd07ab500052b8c661832f\"/>",
+ "<property:Has_subobject-23aux rdf:resource=\"&wiki;Rdf-2D3-23Caract-C3-A8res_sp-C3-A9ciaux\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D3-23_c14ce3099ebd07ab500052b8c661832f\">",
+ "<property:Has_page_property_for_rdf rdf:resource=\"&wiki;I-2D-2D11-2D-2DO\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D3-23Caract-C3-A8res_sp-C3-A9ciaux\">",
+ "<property:Has_text_property_for_rdf rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">{({[[&amp;,,;-]]})}</property:Has_text_property_for_rdf>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AHas_subobject-23aux\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#3 Date output",
+ "exportcontroller": {
+ "print-pages": [
+ "Rdf-4"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D4\">",
+ "<property:Has_date_property_for_rdf rdf:datatype=\"http://www.w3.org/2001/XMLSchema#date\">2014-12-31Z</property:Has_date_property_for_rdf>",
+ "<property:Has_date_property_for_rdf-23aux rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">2457022.5</property:Has_date_property_for_rdf-23aux>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D4-23_2c6937c91895c958f837a25691dd53c0\">",
+ "<property:Has_date_property_for_rdf rdf:datatype=\"http://www.w3.org/2001/XMLSchema#date\">1970-01-01Z</property:Has_date_property_for_rdf>",
+ "<property:Has_date_property_for_rdf-23aux rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">2440587.5</property:Has_date_property_for_rdf-23aux>",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AHas_date_property_for_rdf\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AHas_date_property_for_rdf-23aux\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#4 Property output, see #795",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Has text property for rdf",
+ "Property:Has page property for rdf",
+ "Property:Has date property for rdf"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AHas_text_property_for_rdf\">",
+ "<rdfs:label>Has text property for rdf</rdfs:label>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_txt\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AHas_page_property_for_rdf\">",
+ "<rdfs:label>Has page property for rdf</rdfs:label>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_wpg\"/>",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AHas_date_property_for_rdf\">",
+ "<rdfs:label>Has date property for rdf</rdfs:label>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_dat\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#type\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#5 Check for proper output despite the use of [[Has subobject:: ... ]] as annotation",
+ "exportcontroller": {
+ "print-pages": [
+ "Rdf-5"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D5\">",
+ "<rdfs:label>Rdf-5</rdfs:label>",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">AA-BB-CC</swivt:wikiPageSortKey>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgExportBCAuxiliaryUse": true,
+ "smwgNamespace": "http://example.org/id/",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_HELP": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0002.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0002.json
new file mode 100644
index 00000000..d2b8221a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0002.json
@@ -0,0 +1,86 @@
+{
+ "description": "Test RDF output for redirected pages (#882)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text property for rdf",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page property for rdf",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date property for rdf",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Rdf-1-redirect",
+ "contents": "[[Has page property for rdf::Test one]] [[Has text property for rdf::Test one]] [[Has date property for rdf::1 Jan 1970]]"
+ },
+ {
+ "page": "Rdf-2-redirect",
+ "contents": "#REDIRECT [[Rdf-1-redirect]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 without backlinks",
+ "exportcontroller": {
+ "print-pages": [
+ "Rdf-1-redirect",
+ "Rdf-2-redirect"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D1-2Dredirect\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D2-2Dredirect\">",
+ "<swivt:redirectsTo rdf:resource=\"&wiki;Rdf-2D1-2Dredirect\"/>\n",
+ "<owl:sameAs rdf:resource=\"&wiki;Rdf-2D1-2Dredirect\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#redirectsTo\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 with enabled backlinks",
+ "exportcontroller": {
+ "print-pages": [
+ "Rdf-1-redirect",
+ "Rdf-2-redirect"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "2",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D1-2Dredirect\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Rdf-2D2-2Dredirect\">",
+ "<swivt:redirectsTo rdf:resource=\"&wiki;Rdf-2D1-2Dredirect\"/>\n",
+ "<owl:sameAs rdf:resource=\"&wiki;Rdf-2D1-2Dredirect\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#redirectsTo\" />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0003.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0003.json
new file mode 100644
index 00000000..903ceeb1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0003.json
@@ -0,0 +1,208 @@
+{
+ "description": "Test RDF output for imported foaf vocabulary (#884, en)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import foaf",
+ "contents": "http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name|Type:Text\n homepage|Type:URL\n mbox|Type:Email\n mbox_sha1sum|Type:Text\n depiction|Type:URL\n phone|Type:Text\n Person|Category\n Organization|Category\n knows|Type:Page\n member|Type:Page\n"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Organization",
+ "contents": "[[Imported from::foaf:Organization]] [[Category:Social entity]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:homepage",
+ "contents": "[[Imported from::foaf:homepage]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:mbox",
+ "contents": "[[Has type::Text]] [[Imported from::foaf:mbox]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:name",
+ "contents": "[[Has type::Text]] [[Imported from::foaf:name]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Foaf:knows",
+ "contents": "[[Has type::Page]] [[Imported from::foaf:knows]]"
+ },
+ {
+ "page": "John Doe",
+ "contents": "[[Foaf:name::John Doe]], [[Foaf:homepage::http://example.org/JohnDoe]] [[Foaf:knows::Jane Doe]]"
+ },
+ {
+ "page": "Jane Doe",
+ "contents": "[[Foaf:name::Jane Doe]], [[Foaf:homepage::http://example.org/JaneDoe]] [[Foaf:knows::John Doe]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "John Doe"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/John_Doe\">",
+ "xmlns:foaf=\"http://xmlns.com/foaf/0.1/",
+ "<foaf:homepage rdf:resource=\"http://example.org/JohnDoe\"/>",
+ "<foaf:knows rdf:resource=\"&wiki;Jane_Doe\"/>",
+ "<foaf:name rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">John Doe</foaf:name>",
+ "<owl:ObjectProperty rdf:about=\"http://xmlns.com/foaf/0.1/homepage\" />",
+ "<owl:ObjectProperty rdf:about=\"http://xmlns.com/foaf/0.1/knows\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://xmlns.com/foaf/0.1/name\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 export with backlinks",
+ "exportcontroller": {
+ "print-pages": [
+ "John Doe",
+ "Jane Doe"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "2",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/John_Doe\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Jane_Doe\">",
+ "<foaf:homepage rdf:resource=\"http://example.org/JaneDoe\"/>",
+ "<foaf:knows rdf:resource=\"&wiki;John_Doe\"/>",
+ "<foaf:name rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Jane Doe</foaf:name>",
+ "<owl:ObjectProperty rdf:about=\"http://xmlns.com/foaf/0.1/knows\">",
+ "<rdfs:label>Foaf:knows</rdfs:label>",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">foaf:knows|http://xmlns.com/foaf/0.1/</swivt:specialImportedFrom>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_wpg\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://xmlns.com/foaf/0.1/homepage\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://xmlns.com/foaf/0.1/name\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#specialImportedFrom\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Foaf:knows"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:ObjectProperty rdf:about=\"http://xmlns.com/foaf/0.1/knows\">",
+ "<rdfs:label>Foaf:knows</rdfs:label>",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">foaf:knows|http://xmlns.com/foaf/0.1/</swivt:specialImportedFrom>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_wpg\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#type\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#3 type definition fetched from import reference",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Foaf:homepage"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:ObjectProperty rdf:about=\"http://xmlns.com/foaf/0.1/homepage\">",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">foaf:homepage|http://xmlns.com/foaf/0.1/</swivt:specialImportedFrom>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_uri\"/>",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#specialImportedFrom\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#4 user declared type definition being replaced by import type reference",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Foaf:mbox"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:ObjectProperty rdf:about=\"http://xmlns.com/foaf/0.1/mbox\">",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">foaf:mbox|http://xmlns.com/foaf/0.1/</swivt:specialImportedFrom>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_ema\"/>",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#specialImportedFrom\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#5 owl:Class / Category encoding, see #1081",
+ "exportcontroller": {
+ "print-pages": [
+ "Category:Organization"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:Class rdf:about=\"http://xmlns.com/foaf/0.1/Organization\">",
+ "<rdfs:label>Organization</rdfs:label>",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">foaf:Organization|http://xmlns.com/foaf/0.1/</swivt:specialImportedFrom>",
+ "<rdfs:subClassOf rdf:resource=\"http://example.org/id/Category-3ASocial_entity\"/>",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#specialImportedFrom\" />",
+ "<owl:Class rdf:about=\"http://example.org/id/Category-3ASocial_entity\" />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespace": "http://example.org/id/",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_CATEGORY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0004.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0004.json
new file mode 100644
index 00000000..4788e278
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0004.json
@@ -0,0 +1,92 @@
+{
+ "description": "Test RDF output generation for `_INST`/`_SUBC` pages (#922, en)",
+ "setup": [
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Rdf-1-category",
+ "contents": "empty"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Rdf-2-subcategory",
+ "contents": "[[Category:Rdf-1-category]]"
+ },
+ {
+ "namespace": "NS_CATEGORY",
+ "page": "Rdf-3-subsubcategory",
+ "contents": "[[Category:Rdf-2-subcategory]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 cat-subcat export without backlinks",
+ "exportcontroller": {
+ "print-pages": [
+ "Category:Rdf-1-category",
+ "Category:Rdf-2-subcategory"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:Class rdf:about=\"http://example.org/id/Category-3ARdf-2D1-2Dcategory\">",
+ "<rdfs:label>Rdf-1-category</rdfs:label>",
+ "<owl:Class rdf:about=\"http://example.org/id/Category-3ARdf-2D2-2Dsubcategory\">",
+ "<rdfs:label>Rdf-2-subcategory</rdfs:label>",
+ "<rdfs:subClassOf rdf:resource=\"http://example.org/id/Category-3ARdf-2D1-2Dcategory\"/>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 cat-subcat export with backlinks (catches subsub-cat)",
+ "exportcontroller": {
+ "print-pages": [
+ "Category:Rdf-1-category",
+ "Category:Rdf-2-subcategory"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<!ENTITY category 'http://example.org/id/Category-3A'>",
+ "<!ENTITY property 'http://example.org/id/Property-3A'>",
+ "<owl:Class rdf:about=\"http://example.org/id/Category-3ARdf-2D1-2Dcategory\">",
+ "<rdfs:label>Rdf-1-category</rdfs:label>",
+ "<owl:Class rdf:about=\"http://example.org/id/Category-3ARdf-2D2-2Dsubcategory\">",
+ "<rdfs:label>Rdf-2-subcategory</rdfs:label>",
+ "<rdfs:subClassOf rdf:resource=\"http://example.org/id/Category-3ARdf-2D1-2Dcategory\"/>",
+ "<owl:Class rdf:about=\"http://example.org/id/Category-3ARdf-2D3-2Dsubsubcategory\">",
+ "<rdfs:label>Rdf-3-subsubcategory</rdfs:label>",
+ "<rdfs:subClassOf rdf:resource=\"http://example.org/id/Category-3ARdf-2D2-2Dsubcategory\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3ASubcategory_of\">",
+ "<rdfs:label>Subcategory of</rdfs:label>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0005.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0005.json
new file mode 100644
index 00000000..1e0daae7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0005.json
@@ -0,0 +1,47 @@
+{
+ "description": "Test RDF wiki-info output (#928, en)",
+ "setup": [],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 simple output",
+ "exportcontroller": {
+ "wiki-info": true,
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Wikisite rdf:about=\"&wiki;#wiki\">",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#siteName\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#pagePrefix\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#smwVersion\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#langCode\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#pageCount\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#contentPageCount\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#mediaCount\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#editCount\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#userCount\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://semantic-mediawiki.org/swivt/1.0#adminCount\" />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0006.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0006.json
new file mode 100644
index 00000000..af2ebd76
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0006.json
@@ -0,0 +1,127 @@
+{
+ "description": "Test RDF output generation for pages that contain `_rec` annotations (#1285, #1275)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "HasTextNumberRecord",
+ "contents": "[[Has type::Record]] [[Has fields::Has text;Has number]]"
+ },
+ {
+ "page": "Example/R0006/1",
+ "contents": "[[Category:R0006]] [[HasTextNumberRecord::Foo;123]]"
+ },
+ {
+ "page": "Example/R0006/2",
+ "contents": "[[Category:R0006]] {{#subobject:|HasTextNumberRecord=Foo;123}}"
+ },
+ {
+ "page": "Example/R0006/3",
+ "contents": "[[Category:R0006]] [[HasTextNumberRecord::Foo;123]] {{#subobject:A1|Has number=123|HasTextNumberRecord=Foo;123}} {{#subobject:A2|Has number=456|HasTextNumberRecord=Foo;123}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 simple record annotation",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0006/1"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:HasTextNumberRecord rdf:resource=\"&wiki;Example/R0006/1-23_e594fde0f37d237549009d2ecebce80e\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0006/1-23_e594fde0f37d237549009d2ecebce80e\">",
+ "<property:Has_number rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">123</property:Has_number>",
+ "<property:Has_text rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Foo</property:Has_text>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AHasTextNumberRecord\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 subobject record annotation",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0006/2"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0006/2\">",
+ "<rdf:type rdf:resource=\"http://example.org/id/Category-3AR0006\"/>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0006/2-23_64dbbe1badeb217858f54cedb983c0ae\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0006/2-23_64dbbe1badeb217858f54cedb983c0ae\">",
+ "<property:HasTextNumberRecord rdf:resource=\"&wiki;Example/R0006/2-23_e594fde0f37d237549009d2ecebce80e\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0006/2-23_e594fde0f37d237549009d2ecebce80e\">",
+ "<property:Has_number rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">123</property:Has_number>",
+ "<property:Has_text rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Foo</property:Has_text>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AHas_subobject\" />",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AHasTextNumberRecord\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2 multiple subobject record annotation, test statement uniqueness (statement order is important)",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0006/3"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "store": {
+ "clear-cache": true
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:HasTextNumberRecord rdf:resource=\"&wiki;Example/R0006/3-23_e594fde0f37d237549009d2ecebce80e\"/>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0006/3-23A1\"/>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0006/3-23A2\"/>",
+ "<property:Has_number rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">123</property:Has_number>\n\t\t<property:Has_text rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Foo</property:Has_text>\n\t\t<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Example/R0006/3#Foo;123</swivt:wikiPageSortKey>",
+ "<property:HasTextNumberRecord rdf:resource=\"&wiki;Example/R0006/3-23_e594fde0f37d237549009d2ecebce80e\"/>\n\t\t<property:Has_number rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">123</property:Has_number>",
+ "<property:HasTextNumberRecord rdf:resource=\"&wiki;Example/R0006/3-23_e594fde0f37d237549009d2ecebce80e\"/>\n\t\t<property:Has_number rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">456</property:Has_number>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0007.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0007.json
new file mode 100644
index 00000000..9b56bc90
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0007.json
@@ -0,0 +1,125 @@
+{
+ "description": "Test RDF output for imported dc/gna vocabulary, owl:AnnotationProperty, owl:DatatypeProperty, owl:ObjectProperty, Equivalent URI (#795, `wgRestrictDisplayTitle`, en)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import dc",
+ "contents": "http://purl.org/dc/elements/1.1/|[http://dublincore.org/documents/dces/ Dublin Core Metadata Element Set, Version 1.1] \n contributor|Type:Text \n coverage|Type:Page \n creator|Type:Text \n date|Type:Text \n description|Type:Text \n format|Type:Page \n identifier|Type:Annotation URI \n language|Type:Text \n publisher|Type:Text \n relation|Type:Page \n rights|Type:Text \n source|Type:Text \n subject|Type:Text \n title|Type:Text \n type|Type:Text \n"
+ },
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import gna",
+ "contents": "http://rs.gbif.org/terms/1.0/|[http://rs.gbif.org/extension/gbif/1.0/ GBIF Global Names Architecture (GNA)] \n Identifier|Type:Page \n isHybrid|Type:Boolean"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Dc:identifier",
+ "contents": "[[Imported from::dc:identifier]] [[Equivalent URI::http://purl.org/dc/elements/1.1/identifier]] {{DISPLAYTITLE:dc:identifier}} [[Category:Dublin Core]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Gna:isHybrid",
+ "contents": "[[Imported from::gna:isHybrid]] [[dc:identifier::http://rs.gbif.org/terms/1.0/isHybrid]] {{DISPLAYTITLE:gna:isHybrid}} [[Category:GNA]] [[Category:GBIF]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Gna:Identifier",
+ "contents": "[[Imported from::gna:Identifier]] {{DISPLAYTITLE:gna:Identifier}} [[Category:GNA]] [[Category:GBIF]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 (is owl:AnnotationProperty)",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Dc:identifier"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:AnnotationProperty rdf:about=\"http://purl.org/dc/elements/1.1/identifier\">",
+ "<owl:equivalentProperty rdf:resource=\"http://purl.org/dc/elements/1.1/identifier\"/>",
+ "<property:Display_title_of rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">dc:identifier</property:Display_title_of>",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">dc:identifier|http://purl.org/dc/elements/1.1/</swivt:specialImportedFrom>",
+ "<rdf:type rdf:resource=\"http://example.org/id/Category-3ADublin_Core\"/>",
+ "<owl:Class rdf:about=\"http://example.org/id/Category-3ADublin_Core\" />",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_anu\"/>",
+ "<rdfs:label>dc:identifier</rdfs:label>",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">dc:identifier</swivt:wikiPageSortKey>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 (is owl:DatatypeProperty, typed boolean)",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Gna:isHybrid"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:DatatypeProperty rdf:about=\"http://rs.gbif.org/terms/1.0/isHybrid\">",
+ "<rdfs:label>gna:isHybrid</rdfs:label>",
+ "<dc:identifier rdf:resource=\"http://rs.gbif.org/terms/1.0/isHybrid\"/>",
+ "<property:Display_title_of rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">gna:isHybrid</property:Display_title_of>",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">gna:isHybrid|http://rs.gbif.org/terms/1.0/</swivt:specialImportedFrom>",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">gna:isHybrid</swivt:wikiPageSortKey>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_boo\"/>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2 (is owl:ObjectProperty, typed page)",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Gna:Identifier"
+ ],
+ "parameters": {
+ "backlinks": false,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:ObjectProperty rdf:about=\"http://rs.gbif.org/terms/1.0/Identifier\">",
+ "<rdfs:label>gna:Identifier</rdfs:label>",
+ "<property:Display_title_of rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">gna:Identifier</property:Display_title_of>",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">gna:Identifier|http://rs.gbif.org/terms/1.0/</swivt:specialImportedFrom>",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">gna:Identifier</swivt:wikiPageSortKey>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_wpg\"/>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgAllowDisplayTitle": true,
+ "wgRestrictDisplayTitle": false,
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespace": "http://example.org/id/",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "NS_CATEGORY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0008.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0008.json
new file mode 100644
index 00000000..2d32b97d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0008.json
@@ -0,0 +1,86 @@
+{
+ "description": "Test RDF output generation on pages that contain incoming error annotations (`wgContLang=en`, `wgLang=es`, syntax=rdf/turtle)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has area without unit",
+ "contents": "[[Has type::Quantity]]"
+ },
+ {
+ "page": "Example/R0008/1",
+ "contents": "[[Has area without unit::1 m]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 incoming (error) is exported in canonical form (especially when user language is different)",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Has area without unit"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AHas_area_without_unit\">",
+ "<rdfs:label>Has area without unit</rdfs:label>",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Has area without unit</swivt:wikiPageSortKey>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_qty\"/>"
+ ],
+ "not-contain": [
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3ATiene_valor_incorrecto_para\">",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Tiene valor incorrecto para</swivt:wikiPageSortKey>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 (turtle)",
+ "exportcontroller": {
+ "syntax": "turtle",
+ "print-pages": [
+ "Property:Has area without unit"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "property:Has_area_without_unit",
+ "rdf:type owl:DatatypeProperty ;",
+ "rdfs:label \"Has area without unit\" ;",
+ "swivt:wikiNamespace \"102\"^^xsd:integer ;",
+ "swivt:wikiPageSortKey \"Has area without unit\" ;",
+ "swivt:type <http://semantic-mediawiki.org/swivt/1.0#_qty> .",
+ "<http://example.org/id/Example/R0008/1-23_ERR3b4d92de525df0eeb65e83ea06e2a5d4>",
+ "swivt:masterPage <http://example.org/id/Example/R0008/1> ;",
+ "property:Has_improper_value_for property:Has_area_without_unit ;"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "wgLang": "es",
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0009.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0009.json
new file mode 100644
index 00000000..263f6d69
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0009.json
@@ -0,0 +1,85 @@
+{
+ "description": "Test RDF output generation that contain a monolingual text annotations `_PDESC` (`wgContLang=en`, `wgLang=es`, syntax=rdf/turtle)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]] [[Has property description::Is a number@en]] [[Has property description::æ•°@ja]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Has number"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AHas_number\">",
+ "<skos:scopeNote xml:lang=\"en\">Is a number</skos:scopeNote>",
+ "<skos:scopeNote xml:lang=\"ja\">æ•°</skos:scopeNote>",
+ "<property:Property_description rdf:resource=\"http://example.org/id/Property-3AHas_number-23_ML13b181afba7d1e489a656a75fa7917b2\"/>",
+ "<property:Property_description rdf:resource=\"http://example.org/id/Property-3AHas_number-23_ML4c33eabf5c7dfbb1292c817504951018\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Property-3AHas_number-23_ML13b181afba7d1e489a656a75fa7917b2\">",
+ "<property:Text rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Is a number</property:Text>",
+ "<property:Language_code rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">en</property:Language_code>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Property-3AHas_number-23_ML4c33eabf5c7dfbb1292c817504951018\">",
+ "<property:Text rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">æ•°</property:Text>",
+ "<property:Language_code rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">ja</property:Language_code>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "syntax": "turtle",
+ "print-pages": [
+ "Property:Has number"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "rdfs:label \"Has number\" ;",
+ "skos:scopeNote \"Is a number\"@en , \"æ•°\"@ja ;",
+ "property:Property_description property:Has_number-23_ML13b181afba7d1e489a656a75fa7917b2 , property:Has_number-23_ML4c33eabf5c7dfbb1292c817504951018 ;",
+ "swivt:wikiPageSortKey \"Has number\" ;",
+ "swivt:type <http://semantic-mediawiki.org/swivt/1.0#_num> .",
+ "property:Language_code \"en\" ;",
+ "property:Text \"Is a number\" .",
+ "property:Language_code \"ja\" ;",
+ "property:Text \"æ•°\" ."
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "en",
+ "wgLang": "es",
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0010.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0010.json
new file mode 100644
index 00000000..ae624221
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0010.json
@@ -0,0 +1,104 @@
+{
+ "description": "Test RDF output on canonical entities (`wgContLang=fr`, `wgLang=es`, syntax=rdf/turtle)",
+ "setup": [
+ {
+ "page": "Example/R0010/1",
+ "contents": "[[Boolean::true]]"
+ },
+ {
+ "page": "Example/R0010/2",
+ "contents": "[[Date::2034]]"
+ },
+ {
+ "page": "Example/R0010/Q1",
+ "contents": "{{#ask: [[Booléen::+]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0010/1"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Special:ExportRDF/Example/R0010/1",
+ "<property:Boolean rdf:datatype=\"http://www.w3.org/2001/XMLSchema#boolean\">true</property:Boolean>"
+ ],
+ "not-contain": [
+ "Sp%C3%A9cial:ExportRDF/Example/R0010/1",
+ "<property:Booleano rdf:datatype=\"http://www.w3.org/2001/XMLSchema#boolean\">true</property:Booleano>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0010/2"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Special:ExportRDF/Example/R0010/2",
+ "<property:Date rdf:datatype=\"http://www.w3.org/2001/XMLSchema#gYear\">2034</property:Date>",
+ "<property:Date-23aux rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">2463963.5</property:Date-23aux>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0010/Q1"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:wikiPageContentLanguage rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">fr</swivt:wikiPageContentLanguage>",
+ "<property:Has_query rdf:resource=\"&wiki;Example/R0010/Q1-23_QUERY5223a22ba7ce6ccf63e5701b6d6093b6\"/>"
+ ],
+ "not-contain": [
+ "Sp%C3%A9cial:ExportRDF/Example/R0010/2",
+ "<property:Booleano rdf:datatype=\"http://www.w3.org/2001/XMLSchema#boolean\">true</property:Booleano>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_CATEGORY": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgContLang": "fr",
+ "wgLang": "es",
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0011.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0011.json
new file mode 100644
index 00000000..f155b51a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0011.json
@@ -0,0 +1,112 @@
+{
+ "description": "Test RDF output generation `skos` import/`skos:altLabel` as Monolingual text (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "NS_MEDIAWIKI",
+ "page": "Smw import skos",
+ "contents": {
+ "import-from": "/../Fixtures/skos-import.txt"
+ }
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has alternative label",
+ "contents": "[[Imported from::skos:altLabel]]"
+ },
+ {
+ "page": "Example/P0440/Triacylglycerol lipase",
+ "contents": "[[Has alternative label::Lipase@en]], [[Has alternative label::Tributyrase@en]], [[Has alternative label::Triglyceride lipase@en]], [[Has alternative label::トリアシルグリセロールリパーゼ@ja]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/P0440/Triacylglycerol lipase"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:Has_alternative_label rdf:resource=\"&wiki;Example/P0440/Triacylglycerol_lipase-23_MLb850763abfc7ff93b2753834b000b7dc\"/>",
+ "<property:Has_alternative_label rdf:resource=\"&wiki;Example/P0440/Triacylglycerol_lipase-23_MLa9c103f4379a94bfab97819dacd3c182\"/>",
+ "<property:Has_alternative_label rdf:resource=\"&wiki;Example/P0440/Triacylglycerol_lipase-23_MLcbdbdd5279ca447e5dc7f78465f45256\"/>",
+ "<property:Has_alternative_label rdf:resource=\"&wiki;Example/P0440/Triacylglycerol_lipase-23_MLca7a57d40b775013e7fcc714ec4da30d\"/>",
+ "<skos:altLabel xml:lang=\"en\">Lipase</skos:altLabel>",
+ "<skos:altLabel xml:lang=\"en\">Tributyrase</skos:altLabel>",
+ "<skos:altLabel xml:lang=\"en\">Triglyceride lipase</skos:altLabel>",
+ "<skos:altLabel xml:lang=\"ja\">トリアシルグリセロールリパーゼ</skos:altLabel>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/P0440/Triacylglycerol_lipase-23_MLb850763abfc7ff93b2753834b000b7dc\">",
+ "<property:Language_code rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">en</property:Language_code>",
+ "<property:Text rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Lipase</property:Text>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AHas_alternative_label\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://www.w3.org/2004/02/skos/core#altLabel\" />"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1",
+ "exportcontroller": {
+ "syntax": "turtle",
+ "print-pages": [
+ "Example/P0440/Triacylglycerol lipase"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "property:Has_alternative_label <http://example.org/id/Example/P0440/Triacylglycerol_lipase-23_MLb850763abfc7ff93b2753834b000b7dc> , <http://example.org/id/Example/P0440/Triacylglycerol_lipase-23_MLa9c103f4379a94bfab97819dacd3c182> , <http://example.org/id/Example/P0440/Triacylglycerol_lipase-23_MLcbdbdd5279ca447e5dc7f78465f45256> , <http://example.org/id/Example/P0440/Triacylglycerol_lipase-23_MLca7a57d40b775013e7fcc714ec4da30d> ;",
+ "skos:altLabel \"Lipase\"@en , \"Tributyrase\"@en , \"Triglyceride lipase\"@en , \"トリアシルグリセロールリパーゼ\"@ja ;"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2",
+ "exportcontroller": {
+ "print-pages": [
+ "Property:Has alternative label"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<owl:DatatypeProperty rdf:about=\"http://www.w3.org/2004/02/skos/core#altLabel\">",
+ "<rdfs:label>Has alternative label</rdfs:label>",
+ "<swivt:specialImportedFrom rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">skos:altLabel|http://www.w3.org/2004/02/skos/core#</swivt:specialImportedFrom>",
+ "<swivt:type rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0#_mlt_rec\"/>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0012.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0012.json
new file mode 100644
index 00000000..67ac9bf3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0012.json
@@ -0,0 +1,100 @@
+{
+ "description": "Test RDF output generation on SubSemanticData traversal (#2177, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "DeepExportRecord",
+ "contents": "[[Has type::Record]] [[Has fields::Monolingual text;Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "DeepDeepExportReference",
+ "contents": "[[Has type::Reference]] [[Has fields::Monolingual text;Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "DeepDeepExportRecord",
+ "contents": "[[Has type::Record]] [[Has fields::DeepDeepExportReference]]"
+ },
+ {
+ "page": "Example/R0012/1",
+ "contents": "{{#subobject: |DeepExportRecord=Test@en;12 |DeepExportRecord=Test@en;123 |DeepExportRecord=Test@en;1234 }}"
+ },
+ {
+ "page": "Example/R0012/2",
+ "contents": "{{#subobject: |DeepDeepExportRecord=Test@en\\;1 Jan 1970 |DeepDeepExportRecord=Test@fr\\;1 Jan 1971 }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 does not cause a SubSemanticDataException during the export",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0012/1"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/1-23_ML2c4c5edb170b331e395a01005cb65358\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/1-23_d5f308a6235110d394024f55f16835f7\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/1-23_6779e00256727fef98705300a8a7a73b\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/1-23_f6e5c74170e0046a78d2712a90970310\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/1-23_04ddc57f1473b963c04af38df2e994a4\">",
+ "<property:Language_code rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">en</property:Language_code>",
+ "<property:Text rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Test</property:Text>",
+ "<property:Monolingual_text-23aux xml:lang=\"en\">Test</property:Monolingual_text-23aux>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 stable IDs and `subobject->record->reference->monolingual text` traversal",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0012/2"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/2-23_ML2c4c5edb170b331e395a01005cb65358\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/2-23_REF1940cba4db3a967bc1d8e0c0a96bbc2e\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/2-23_7d9ab26348dedff9e03af7e8bc8d440d\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/2-23_ML18e8304d117e9f958205000e055d12f3\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/2-23_REFd17d8d8ba79f00d64f5b9c51f92e0867\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/2-23_797f86a0718f4fdec776197cf5adea93\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0012/2-23_7f24e1a1c0ee4de54d6344daae7375b5\">",
+ "<property:Date rdf:datatype=\"http://www.w3.org/2001/XMLSchema#date\">1971-01-01Z</property:Date>",
+ "<property:Date rdf:datatype=\"http://www.w3.org/2001/XMLSchema#date\">1970-01-01Z</property:Date>",
+ "<property:Monolingual_text-23aux xml:lang=\"en\">Test</property:Monolingual_text-23aux>",
+ "<property:Monolingual_text-23aux xml:lang=\"fr\">Test</property:Monolingual_text-23aux>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0013.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0013.json
new file mode 100644
index 00000000..d232c5a8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0013.json
@@ -0,0 +1,105 @@
+{
+ "description": "Test RDF output generation `_uri`/`_ema`/`_tel` with spaces/underscore (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has telephone number",
+ "contents": "[[Has type::Telephone number]]"
+ },
+ {
+ "page": "Example/R0013/1",
+ "contents": "[[Has url::http://example.org/Foo bar]] [[Has url::http://example.org/Foo%20bar]] [[Has url::http://example.org/Foo_bar]]"
+ },
+ {
+ "page": "Example/R0013/2",
+ "contents": "[[Email::john_doe@example.org]]"
+ },
+ {
+ "page": "Example/R0013/3",
+ "contents": "[[Has telephone number::+1 201 555 5555]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 url with underscore",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0013/1"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:Has_url rdf:resource=\"http://example.org/Foo_bar\"/>"
+ ],
+ "not-contain": [
+ "<property:Has_url rdf:resource=\"http://example.org/Foo bar\"/>",
+ "<property:Has_url rdf:resource=\"http://example.org/Foo%20bar\"/>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1 email with underscore",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0013/2"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:Email rdf:resource=\"mailto:john_doe@example.org\"/>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2 tle with spaces",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0013/3"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:Has_telephone_number rdf:resource=\"tel:+1-201-555-5555\"/>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0014.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0014.json
new file mode 100644
index 00000000..18b9b771
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0014.json
@@ -0,0 +1,76 @@
+{
+ "description": "Test RDF output generation on non-latin URI/IRI export (#2188, `smwgExportResourcesAsIri=false`, `wgContLang=ru`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Заголовок",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Тип публикации",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Журнал",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Год",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/R0014/Заголовок",
+ "contents": "[[Заголовок::Pollen Limitation]] [[Журнал::Arctic, Antarctic and Alpine Research]] [[Год::2009]] [[Тип публикации::СтатьÑ]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0014/Заголовок"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0014/-D0-97-D0-B0-D0-B3-D0-BE-D0-BB-D0-BE-D0-B2-D0-BE-D0-BA\">",
+ "<rdfs:label>Example/R0014/Заголовок</rdfs:label>",
+ "<wiki:Property-3A-D0-93-D0-BE-D0-B4 rdf:datatype=\"http://www.w3.org/2001/XMLSchema#gYear\">2009</wiki:Property-3A-D0-93-D0-BE-D0-B4>",
+ "<wiki:Property-3A-D0-96-D1-83-D1-80-D0-BD-D0-B0-D0-BB rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Arctic, Antarctic and Alpine Research</wiki:Property-3A-D0-96-D1-83-D1-80-D0-BD-D0-B0-D0-BB>",
+ "<wiki:Property-3A-D0-97-D0-B0-D0-B3-D0-BE-D0-BB-D0-BE-D0-B2-D0-BE-D0-BA rdf:resource=\"&wiki;Pollen_Limitation\"/>",
+ "<wiki:Property-3A-D0-A2-D0-B8-D0-BF_-D0-BF-D1-83-D0-B1-D0-BB-D0-B8-D0-BA-D0-B0-D1-86-D0-B8-D0-B8 rdf:resource=\"&wiki;-D0-A1-D1-82-D0-B0-D1-82-D1-8C-D1-8F\"/>",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3A-D0-93-D0-BE-D0-B4\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3A-D0-93-D0-BE-D0-B4-23aux\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3A-D0-96-D1-83-D1-80-D0-BD-D0-B0-D0-BB\" />",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3A-D0-97-D0-B0-D0-B3-D0-BE-D0-BB-D0-BE-D0-B2-D0-BE-D0-BA\" />",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3A-D0-A2-D0-B8-D0-BF_-D0-BF-D1-83-D0-B1-D0-BB-D0-B8-D0-BA-D0-B0-D1-86-D0-B8-D0-B8\" />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "ru",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgExportResourcesAsIri": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0015.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0015.json
new file mode 100644
index 00000000..2a4fa481
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0015.json
@@ -0,0 +1,77 @@
+{
+ "description": "Test RDF output generation on non-latin URI/IRI export (#2188, `smwgExportResourcesAsIri=true`, `wgContLang=ru`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Заголовок",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Тип публикации",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Журнал",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Год",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/R0015/Заголовок",
+ "contents": "[[Заголовок::Pollen Limitation]] [[Журнал::Arctic, Antarctic and Alpine Research]] [[Год::2009]] [[Тип публикации::СтатьÑ]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0015/Заголовок"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0015/Заголовок\">",
+ "<rdfs:label>Example/R0015/Заголовок</rdfs:label>",
+ "<property:Год rdf:datatype=\"http://www.w3.org/2001/XMLSchema#gYear\">2009</property:Год>",
+ "<property:Год-23aux rdf:datatype=\"http://www.w3.org/2001/XMLSchema#double\">2454832.5</property:Год-23aux>",
+ "<property:Журнал rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Arctic, Antarctic and Alpine Research</property:Журнал>",
+ "<property:Заголовок rdf:resource=\"&wiki;Pollen_Limitation\"/>",
+ "<property:Тип_публикации rdf:resource=\"&wiki;СтатьÑ\"/>",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AГод\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AГод-23aux\" />",
+ "<owl:DatatypeProperty rdf:about=\"http://example.org/id/Property-3AЖурнал\" />",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AЗаголовок\" />",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AТип_публикации\" />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "ru",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgExportResourcesAsIri": true,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0016.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0016.json
new file mode 100644
index 00000000..53a199e9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0016.json
@@ -0,0 +1,105 @@
+{
+ "description": "Test RDF output generation with special characters (#2188, `smwgExportResourcesAsIri=false`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "page": "Example/R0016/1/特殊字符",
+ "contents": "{{#subobject: ^[0-9]*$ |特殊字符=^[0-9]*$ }}"
+ },
+ {
+ "page": "Example/R0016/2/特殊字符",
+ "contents": "{{#subobject: {({[[&,,;-.]]})} |特殊字符={({[[&,,;-]]})} }}"
+ },
+ {
+ "page": "Example/R0016/3/特殊 字符",
+ "contents": "{{#subobject: <> |特殊字符=<>\\'/\" }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0016/1/特殊字符"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0016/1/-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6\">",
+ "<rdfs:label>Example/R0016/1/特殊字符</rdfs:label>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0016/1/-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6-23-5E-5B0-2D9-5D-2A-24\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0016/1/-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6-23_ERRb4cc1ce66e816f93b716adeeddb0fa46\">",
+ "<property:Has_improper_value_for rdf:resource=\"&wiki;Property-3A-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6\"/>",
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Example/R0016/1/特殊字符</swivt:wikiPageSortKey>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0016/2/特殊字符"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0016/2/-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6\">",
+ "<rdfs:label>Example/R0016/2/特殊字符</rdfs:label>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0016/2/-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6-23-7B-28-7B-5B-5B-26-2C-2C-3B-2D.-5D-5D-7D-29-7D\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0016/2/-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6-23_ERRb4cc1ce66e816f93b716adeeddb0fa46\">",
+ "<property:Has_improper_value_for rdf:resource=\"&wiki;Property-3A-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6\"/>"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0016/3/特殊 字符"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0016/3/-E7-89-B9-E6-AE-8A_-E5-AD-97-E7-AC-A6\">",
+ "<rdfs:label>Example/R0016/3/特殊 字符</rdfs:label>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0016/3/-E7-89-B9-E6-AE-8A_-E5-AD-97-E7-AC-A6-23-3C-3E\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0016/3/-E7-89-B9-E6-AE-8A_-E5-AD-97-E7-AC-A6-23_ERRb4cc1ce66e816f93b716adeeddb0fa46\">",
+ "<property:Has_improper_value_for rdf:resource=\"&wiki;Property-3A-E7-89-B9-E6-AE-8A-E5-AD-97-E7-AC-A6\"/>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgExportResourcesAsIri": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0017.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0017.json
new file mode 100644
index 00000000..bb427db3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0017.json
@@ -0,0 +1,104 @@
+{
+ "description": "Test RDF output generation with special characters (#2188, `smwgExportResourcesAsIri=true`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "page": "Example/R0017/1/特殊字符",
+ "contents": "{{#subobject: ^[0-9]*$ |特殊字符=^[0-9]*$ }}"
+ },
+ {
+ "page": "Example/R0017/2/特殊字符",
+ "contents": "{{#subobject: {({[[&,,;-.]]})} |特殊字符={({[[&,,;-]]})} }}"
+ },
+ {
+ "page": "Example/R0017/3/特殊 字符",
+ "contents": "{{#subobject: <> |特殊字符=<>\\'/\" }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0017/1/特殊字符"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/1/特殊字符\">",
+ "<rdfs:label>Example/R0017/1/特殊字符</rdfs:label>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0017/1/特殊字符-23-5E-5B0-2D9-5D-2A-24\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/1/特殊字符-23_ERRb4cc1ce66e816f93b716adeeddb0fa46\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/1/特殊字符-23-5E-5B0-2D9-5D-2A-24\">"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#1",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0017/2/特殊字符"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/2/特殊字符\">",
+ "<rdfs:label>Example/R0017/2/特殊字符</rdfs:label>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0017/2/特殊字符-23-7B-28-7B-5B-5B-26-2C-2C-3B-2D.-5D-5D-7D-29-7D\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/2/特殊字符-23_ERRb4cc1ce66e816f93b716adeeddb0fa46\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/2/特殊字符-23-7B-28-7B-5B-5B-26-2C-2C-3B-2D.-5D-5D-7D-29-7D\">"
+ ]
+ }
+ },
+ {
+ "type": "rdf",
+ "about": "#2",
+ "exportcontroller": {
+ "print-pages": [
+ "Example/R0017/3/特殊 字符"
+ ],
+ "parameters": {
+ "backlinks": true,
+ "recursion": "1",
+ "revisiondate": false
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/3/特殊_字符\">",
+ "<rdfs:label>Example/R0017/3/特殊 字符</rdfs:label>",
+ "<property:Has_subobject rdf:resource=\"&wiki;Example/R0017/3/特殊_字符-23-3C-3E\"/>",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/3/特殊_字符-23_ERRb4cc1ce66e816f93b716adeeddb0fa46\">",
+ "<swivt:Subject rdf:about=\"http://example.org/id/Example/R0017/3/特殊_字符-23-3C-3E\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgExportResourcesAsIri": true,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0018.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0018.json
new file mode 100644
index 00000000..ffefb633
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0018.json
@@ -0,0 +1,46 @@
+{
+ "description": "Test RDF output generation with special characters (`smwgExportResourcesAsIri=true`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/R0018/1",
+ "contents": "[[Has url::https://example.org/public/item#Foo\"Bar\"]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0 (double quotes)",
+ "dumpRDF": {
+ "parameters": {
+ "page": "Example/R0018/1"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<property:Has_url rdf:resource=\"https://example.org/public/item#Foo%22Bar%22\"/>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgExportBCNonCanonicalFormUse": false,
+ "smwgExportResourcesAsIri": true,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0019.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0019.json
new file mode 100644
index 00000000..3e197244
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0019.json
@@ -0,0 +1,52 @@
+{
+ "description": "Test RDF output on `swivt:sort` with enabled collation (#2065, `smwgEntityCollation=uppercase`, `smwgSparqlQFeatures=SMW_SPARQL_QF_COLLATION`, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/R0019/1",
+ "contents": "[[Has url::https://example.org/Foo]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "dumpRDF": {
+ "parameters": {
+ "page": "Example/R0019/1"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<swivt:wikiPageSortKey rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">Example/R0019/1</swivt:wikiPageSortKey>",
+ "<swivt:sort rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">EXAMPLE/R0019/1</swivt:sort>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "smwgEntityCollation": "uppercase",
+ "smwgSparqlQFeatures": [
+ "SMW_SPARQL_QF_REDI",
+ "SMW_SPARQL_QF_SUBP",
+ "SMW_SPARQL_QF_SUBC",
+ "SMW_SPARQL_QF_COLLATION"
+ ],
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0020.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0020.json
new file mode 100644
index 00000000..07600613
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/r-0020.json
@@ -0,0 +1,45 @@
+{
+ "description": "Test RDF output on `/` in porperty name (#3134)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "R0020/URL",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/R0020/1",
+ "contents": "[[R0020/URL::https://example.org/Foo]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "rdf",
+ "about": "#0",
+ "dumpRDF": {
+ "parameters": {
+ "page": "Example/R0020/1"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<wiki:Property-3AR0020-2FURL rdf:resource=\"https://example.org/Foo\"/>",
+ "<owl:ObjectProperty rdf:about=\"http://example.org/id/Property-3AR0020-2FURL\" />"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "smwgNamespace": "http://example.org/id/"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0001.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0001.json
new file mode 100644
index 00000000..9f6cc902
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0001.json
@@ -0,0 +1,68 @@
+{
+ "description": "Test output of `Special:Properties` (`wgContLang=en`, skip-on sqlite)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has test blob property",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Is restricted property",
+ "contents": "[[Has type::Text]] [[Allows value::open]] [[Allows value::closed]]"
+ }
+ ],
+ "beforeTest": {
+ "maintenance-run": {
+ "rebuildPropertyStatistics": true
+ }
+ },
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 search for user-defined property to contain",
+ "special-page": {
+ "page": "Properties",
+ "query-parameters": [],
+ "request-parameters": {
+ "property": "test blob"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Property:Has_test_blob_property\" title=\"ID:",
+ "Has test blob property"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 search for pre-defined property",
+ "special-page": {
+ "page": "Properties",
+ "query-parameters": [],
+ "request-parameters": {
+ "property": "Allow"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Property:Allows_value\" title=\"ID: 14 (_PVAL)\">Allows value</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPropertyZeroCountDisplay": true
+ },
+ "meta": {
+ "skip-on": {
+ "sqlite": "Returns a `database is locked`"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0002.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0002.json
new file mode 100644
index 00000000..a85723ad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0002.json
@@ -0,0 +1,586 @@
+{
+ "description": "Test output from `Special:SearchByProperty` for `_num`, `_txt`, `_tel` (#1728, #2009, `wgContLang=en`, `wgLang=en`, skip-on sqlite, postgres)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "P-20-25",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]] [[Display precision of::2]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has telephone number",
+ "contents": "[[Has type::Telephone number]]"
+ },
+ {
+ "page": "Example/S0002/1",
+ "contents": "[[Has text::S0002]]"
+ },
+ {
+ "page": "Example/S0002/2",
+ "contents": "[[Has text::foo bar]]"
+ },
+ {
+ "page": "Example/S0002/3",
+ "contents": "[[Has number::3.555567]]"
+ },
+ {
+ "page": "Example/S0002/4",
+ "contents": "[[Has number::1.2e-13]]"
+ },
+ {
+ "page": "Example/S0002/5",
+ "contents": "[[Has telephone number::+1-201-555-0123]]"
+ },
+ {
+ "page": "Example/S0002/6",
+ "contents": "[[Has text::foo-bar]]"
+ },
+ {
+ "page": "Example/S0002/7",
+ "contents": "[[Has text::foo-123#&^*%<1?=/->\"']]"
+ },
+ {
+ "page": "Example/S0002/8",
+ "contents": "[[Has text::foo-123_abc']]"
+ },
+ {
+ "page": "Example/S0002/9",
+ "contents": "[[Has number::-20]]"
+ },
+ {
+ "page": "Example/S0002/10",
+ "contents": "[[Has number::-25]]"
+ },
+ {
+ "page": "Example/S0002/11",
+ "contents": "[[Has text::AA-2000]]"
+ },
+ {
+ "page": "Example/S0002/12",
+ "contents": "[[Has text::AA-20-2D00]]"
+ },
+ {
+ "page": "Example/S0002/13",
+ "contents": "[[Has text::AA-20-2500]]"
+ },
+ {
+ "page": "Example/S0002/14",
+ "contents": "[[Has text::AA-2000 with_&]]"
+ },
+ {
+ "page": "Example/S0002/15",
+ "contents": "[[P-20-25::-25]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 search for user-defined property to contain",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has_text"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<li>S0002&#160;&#160;",
+ "title=\"Special:SearchByProperty/:Has-20text/S0002\">+</a></span>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 value to contain `_`",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has text",
+ "value": "foo bar"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F2",
+ "<small>(foo bar)</small>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 value to contain ` `",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has text",
+ "value": "foo bar"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F2",
+ "<small>(foo bar)</small>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3 value input not be constraint by precision",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has number",
+ "value": "3.555567"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F3",
+ "<small>(3.556)</small>"
+ ],
+ "not-contain": [
+ "value=3.56"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#4 do not encode e- for a number value",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has number",
+ "value": "1.2e-13"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F4",
+ "<small>(1.2e-13)</small>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#5 same as 1.2e-13",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has number",
+ "value": "0.00000000000012"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F4",
+ "<small>(1.2e-13)</small>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#6 telephone number",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has telephone number",
+ "value": "+1-201-555-0123"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F5",
+ "+1-201-555-0123"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#6 telephone number",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has telephone number",
+ "value": "+1-201-555-0123"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F5",
+ "+1-201-555-0123"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#7 invalid property and avoid a `...must be an instance of SMWDIProperty, instance of SMWDIError given...`",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": ">[[Foo",
+ "value": ""
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "&gt;[[Foo"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#8 text with dash",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "foo-bar"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F6",
+ "foo-bar"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#9 text with dash",
+ "skip-on": {
+ "virtuoso": "Failed asserting that 0 matches expected 2, don't know why!"
+ },
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "foo-2Dbar"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F6",
+ "foo-bar"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#10 text with special html chars",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "foo-123#&^*%<1?=/->\"'"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F7",
+ "foo-123#&amp;^*%&lt;1?=/-&gt;\"'"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#11 text with -/_",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "foo-123_abc'"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F8",
+ "<small>(foo-123_abc')</small>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#12 Number/-20 unescape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has number",
+ "value": "-20"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F9",
+ "<small>(-20)</small>",
+ "value=\"-20\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#13 Number/-20 escape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "/:Has-20number/-2D20",
+ "request-parameters":{}
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F9",
+ "<small>(-20)</small>",
+ "value=\"-20\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#13 Number/-25 unescape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has number",
+ "value": "-25"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F10",
+ "<small>(-25)</small>",
+ "value=\"-25\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#14 Number/-25 escape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "/:Has-20number/-2D25",
+ "request-parameters":{}
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F10",
+ "<small>(-25)</small>",
+ "value=\"-25\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#15 Text/-20 unescape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "AA-2000"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F11",
+ "<small>(AA-2000)</small>",
+ "value=\"AA-2000\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#16 Text/-20 escape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "/:Has-20text/AA-2D2000",
+ "request-parameters":{}
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F11",
+ "<small>(AA-2000)</small>",
+ "value=\"AA-2000\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#15 Text/-20-2D unescape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "AA-20-2D00"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F12",
+ "<small>(AA-20-2D00)</small>",
+ "value=\"AA-20-2D00\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#16 Text/-20-2D escape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "/:Has-20text/AA-2D20-2D2D00",
+ "request-parameters":{}
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F12",
+ "<small>(AA-20-2D00)</small>",
+ "value=\"AA-20-2D00\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#17 Text/-20-25 unescape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "AA-20-2500"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F13",
+ "<small>(AA-20-2500)</small>",
+ "value=\"AA-20-2500\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#18 Text/-20-25 escape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "/:Has-20text/AA-2D20-2D2500",
+ "request-parameters":{}
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F13",
+ "<small>(AA-20-2500)</small>",
+ "value=\"AA-20-2500\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#19 Text/-20_& unescape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "Has text",
+ "value": "AA-2000 with_&"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F14",
+ "<small>(AA-2000 with_&amp;)</small>",
+ "value=\"AA-2000 with_&amp;\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#20 Text/-20_& escape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "/:Has-20text/AA-2D2000-20with-5F-26",
+ "request-parameters":{}
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F14",
+ "<small>(AA-2000 with_&amp;)</small>",
+ "value=\"AA-2000 with_&amp;\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#21 Property-20-25 unescape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "",
+ "request-parameters":{
+ "property": "P-20-25",
+ "value": "-25"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F15",
+ "<small>(-25)</small>",
+ "value=\"P-20-25\"",
+ "value=\"-25\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#22 Property-20-25 escape",
+ "special-page": {
+ "page":"SearchByProperty",
+ "query-parameters": "/:P-2D20-2D25/-2D25",
+ "request-parameters":{}
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0002-2F15",
+ "<small>(-25)</small>",
+ "value=\"P-20-25\"",
+ "value=\"-25\""
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en"
+ },
+ "meta": {
+ "skip-on": {
+ "sqlite": "Returns a `database is locked`",
+ "postgres": "The table update lacks behind"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0003.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0003.json
new file mode 100644
index 00000000..a4fb17c6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0003.json
@@ -0,0 +1,131 @@
+{
+ "description": "Test `Special:Ask` output for `format=rdf`/`format=json`/DISPLAYTITLE (#1453, #1619, `wgRestrictDisplayTitle`, `wgContLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has boolean",
+ "contents": "[[Has type::Boolean]]"
+ },
+ {
+ "page": "Example/S0003/1",
+ "contents": "[[Has boolean::true]] [[Category:S0003]]"
+ },
+ {
+ "page": "Example/S0003/2",
+ "contents": "{{DISPLAYTITLE:FOO-S0003}} [[Category:S0003]]"
+ },
+ {
+ "page": "Example/S0003/Q1",
+ "contents": "{{#ask: [[Category:S0003]] |?Category |?Has boolean=Text |link=none |format=rdf }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/S0003/Q1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ],
+ "propertyValues": []
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "-5B-5BCategory:S0003-5D-5D/-3FCategory/-3FHas-20boolean=Text/mainlabel=/limit=100/offset=0/format=rdf/link=none\">RDF</a>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0003-5D-5D/-3FCategory/-3FHas-20boolean=Text/mainlabel=/limit=100/offset=0/format=rdf/link=none",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<rdfs:label>Example/S0003/1</rdfs:label>",
+ "<property:Has_boolean rdf:datatype=\"http://www.w3.org/2001/XMLSchema#boolean\">true</property:Has_boolean>",
+ "<swivt:type rdf:resource=\"http://example.org/id/Category-3AS0003\"/>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2",
+ "skip-on": {
+ "mw-1.19.20": "Skipping because of spaces in output fields being different",
+ "mw-1.22.12": "Skipping because of spaces in output fields being different"
+ },
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0003-5D-5D/-3FCategory/-3FHas-20boolean=Text/mainlabel=/limit=100/offset=0/format=json/unescape=true/prettyprint=true/link=none",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "\"fulltext\": \"Category:S0003\"",
+ "\"fulltext\": \"Example/S0003/1\"",
+ "\"key\": \"Has_boolean\""
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3 (link=subject)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0003-5D-5D/mainlabel=/offset=0/format=table/link=subject",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "FOO-S0003"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#4 (link=none)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0003-5D-5D/mainlabel=/offset=0/format=table/link=none",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/S0003/2"
+ ],
+ "not-contain": [
+ "FOO-S0003"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en",
+ "wgRestrictDisplayTitle": false,
+ "smwgNamespace": "http://example.org/id/",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0004.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0004.json
new file mode 100644
index 00000000..d2ea9179
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0004.json
@@ -0,0 +1,49 @@
+{
+ "description": "Test `Special:Browse` output for `_dat` (`wgContLang=en`, `wgLang=ja`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/S0004/1",
+ "contents": "[[Has date::12 Jan 1991 8:56]] [[Category:S0004]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (output is localized, info link is in accordance with content lang.)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0004/1",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-value\">1991年1月12日 (土) 08:56:00&#160;&#160;",
+ "title=\"Special:SearchByProperty/:Has-20date/12-20January-201991-2008:56:00\">+</a></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "ja",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0005.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0005.json
new file mode 100644
index 00000000..9e590cd6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0005.json
@@ -0,0 +1,83 @@
+{
+ "description": "Test `Special:Browse` output for `_dat`, '_REDI' (`wgContLang=en`, `wgLang=en`, `smwgDVFeatures=SMW_DV_TIMEV_CM | SMW_DV_WPV_DTITLE`, `wgRestrictDisplayTitle=false`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/S0005/1",
+ "contents": "[[Has date::12 Jan 1991 8:56]] [[Has date::12 Jan 1345]] [[Category:S0004]]"
+ },
+ {
+ "page": "Example/S0005/2",
+ "contents": "#REDIRECT [[Example/S0005/3]]"
+ },
+ {
+ "page": "Example/S0005/3",
+ "contents": "{{DISPLAYTITLE:ABC}}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0005/1",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-value\">08:56:00, 12 January 1991&#160;&#160;",
+ "title=\"Special:SearchByProperty/:Has-20date/12-20January-201991-2008:56:00\">+</a></span>",
+ "<span class=\"smwb-value\">January 12, 1345 <sup>JL</sup>&#160;&#160;",
+ "title=\"Special:SearchByProperty/:Has-20date/12-20January-201345-20JL\">+</a></span>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (redirect to show source page instead of DISPLAYTITLE)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0005/3",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "class=\"mw-redirect\" title=\"Example/S0005/2\">Example/S0005/2"
+ ],
+ "not-contain": [
+ "class=\"mw-redirect\" title=\"Example/S0005/2\">ABC"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ },
+ "wgRestrictDisplayTitle": false,
+ "smwgDVFeatures": [
+ "SMW_DV_TIMEV_CM",
+ "SMW_DV_WPV_DTITLE"
+ ]
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0006.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0006.json
new file mode 100644
index 00000000..e1b724a4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0006.json
@@ -0,0 +1,50 @@
+{
+ "description": "Test output of `Special:WantedProperties` (`wgContLang=en`, `wgLang=en`, skip-on sqlite)",
+ "setup": [
+ {
+ "page": "Example/S0006/1",
+ "contents": "[[Has property without type::123]]"
+ },
+ {
+ "page": "Example/S0006/2",
+ "contents": "[[Has property without type::456]]"
+ },
+ {
+ "page": "Example/S0006/3",
+ "contents": "[[Has property without type::789]]"
+ }
+ ],
+ "beforeTest": {
+ "maintenance-run": {
+ "rebuildPropertyStatistics": true
+ }
+ },
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (whether to appear on the list of wanted properties)",
+ "special-page": {
+ "page": "WantedProperties",
+ "query-parameters": [],
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "Property:Has property without type (page does not exist)"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "skip-on": {
+ "sqlite": "Returns a `database is locked`"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0007.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0007.json
new file mode 100644
index 00000000..aa7f1900
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0007.json
@@ -0,0 +1,44 @@
+{
+ "description": "Test output of `Special:UnusedProperties` (`wgContLang=en`, `wgLang=en`, skip-on sqlite, 1.19)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Unused typed property",
+ "contents": "[[Has type::Page]] [[Has property description::Typed property@en]]"
+ }
+ ],
+ "beforeTest": {
+ "maintenance-run": {
+ "rebuildPropertyStatistics": true
+ }
+ },
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (whether to appear in the list of unused properties without subproperty)",
+ "special-page": {
+ "page": "UnusedProperties",
+ "query-parameters": [],
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "Property:Unused typed property"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en"
+ },
+ "meta": {
+ "skip-on": {
+ "sqlite": "Returns a `database is locked`",
+ "mw-1.19.20": "The table update on 1.19 lacks behind"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0008.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0008.json
new file mode 100644
index 00000000..4dbcfde9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0008.json
@@ -0,0 +1,161 @@
+{
+ "description": "Test `Special:Browse` output for `_dat`, `_boo`, `_sobj`, `_uri` (`wgContLang=en`, `wgLang=es`, skip-on 1.25.6)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has boolean",
+ "contents": "[[Has type::Boolean]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has atomic mass unit",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 u]] [[Corresponds to::1.660539040e-27 kg]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has url",
+ "contents": "[[Has type::URL]]"
+ },
+ {
+ "page": "Example/S0008/1",
+ "contents": "[[Has date::12 Jan 1991 8:56]] [[Has boolean::true]] [[Category:S0008]]"
+ },
+ {
+ "page": "Example/S0008/2",
+ "contents": "[[Has number::0.00000000000012]] [[Has number::72.769482308]] [[Has number::1.334e-13]] [[Category:S0008]]"
+ },
+ {
+ "page": "Example/S0008/3 (Hydrogen-1 atom)",
+ "contents": "[[Has atomic mass unit::1.007825 u]] [[Category:S0008]]"
+ },
+ {
+ "page": "Example/S0008/4",
+ "contents": "{{#subobject:ABC::DEF|Has number=123}}"
+ },
+ {
+ "page": "Example/S0008/5",
+ "contents": "[[Has url::http://example.org/some1::23:334/::56]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0008/1",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-value\">verdadero&#160;&#160;",
+ "SearchByProperty/:Has-20boolean/true",
+ "<span class=\"smwb-value\">08:56:00 12 ene 1991&#160;&#160;"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (numbers)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0008/2",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-value\">1,2e-13&#160;&#160;",
+ "<span class=\"smwb-value\">72,769&#160;&#160;",
+ "<span class=\"smwb-value\">1,334e-13&#160;&#160;",
+ "Special:SearchByProperty/:Has-20number/1.2e-2D13",
+ "Special:SearchByProperty/:Has-20number/72.769482308",
+ "Special:SearchByProperty/:Has-20number/1.334e-2D13"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (quantity)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0008/3 (Hydrogen-1 atom)",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-value\">1,008&#160;u (1,673533e-27&#160;kg)&#160;&#160;",
+ "Special:SearchByProperty/:Has-20atomic-20mass-20unit/1.007825-20u"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3 named subobject contains ::",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": ":Example-2FS0008-2F4-23ABC::DEF",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-value\">123&#160;&#160;",
+ "Special:SearchByProperty/:Has-20number/123"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#4 url contains :: (encoded with -3A)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0008/5",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "href=\"http://example.org/some1::23:334/::56\">http://example.org/some1::23:334/::56</a>&#160;&#160;",
+ "Special:SearchByProperty/:Has-20url/http-2D3A-2F-2Fexample.org-2Fsome1-2D3A-2D3A23-2D3A334-2F-2D3A-2D3A56"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "es",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "mw-1.25.6": "Somehow the content lang is not set correctly on Travis (locally works fine)."
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0009.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0009.json
new file mode 100644
index 00000000..70c1f55f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0009.json
@@ -0,0 +1,67 @@
+{
+ "description": "Test output in `Special:Search` for SMWSearch (`wgLanguageCode=en`, `wgContLang=en`, `wgSearchType=SMWSearch`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/S0009/1",
+ "contents": "[[Has text::Some text to search]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0",
+ "subject": "Example/S0009/1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has_text"
+ ],
+ "propertyValues": [
+ "Some text to search"
+ ]
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 results matched by the SMWSearch extension",
+ "special-page": {
+ "page": "Search",
+ "query-parameters": "",
+ "request-parameters": {
+ "search": "[[Has text::~*Some text*]]"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<ul class='mw-search-results'>",
+ "Example/S0009/1"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en",
+ "wgSearchType": "SMWSearch",
+ "wgCapitalLinks" : true,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0010.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0010.json
new file mode 100644
index 00000000..185bd61a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0010.json
@@ -0,0 +1,56 @@
+{
+ "description": "Test output from `Special:SearchByProperty` / `_dat` (#1922, `wgContLang=en`, `wgLang=es`, skip-on sqlite)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/S0010/1",
+ "contents": "[[Has date::1 Jan 1970]]"
+ },
+ {
+ "page": "Example/S0010/2",
+ "contents": "[[Has date::2 Dec 2100 12:12:12]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 infolinks on value are content lang. formatted",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "property": "Has date"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<li>1 ene 1970&#160;&#160;",
+ "title=\"Special:SearchByProperty/:Has-20date/1-20January-201970\">+</a>",
+ "<li>12:12:12 2 dic 2100&#160;&#160;",
+ "title=\"Special:SearchByProperty/:Has-20date/2-20December-202100-2012:12:12\">+</a>"
+ ],
+ "not-contain": [
+ "title=\"Special:SearchByProperty/:Has-20date/1-20ene-201970\">+</a>",
+ "title=\"Special:SearchByProperty/:Has-20date/12:12:12-202-20dic-202100\">+</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "es",
+ "wgLanguageCode": "en"
+ },
+ "meta": {
+ "skip-on": {
+ "sqlite": "Returns a `database is locked`"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0011.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0011.json
new file mode 100644
index 00000000..7b8e4074
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0011.json
@@ -0,0 +1,136 @@
+{
+ "description": "Test `Special:Ask` output `#ask` intro/outro link/template parse (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "S0011-Template",
+ "contents": "<includeonly>{{{test}}} link [[{{{test}}}]]</includeonly>"
+ },
+ {
+ "page": "Example/S0011/1",
+ "contents": "[[Has text::abc]] [[Category:S0011]]"
+ },
+ {
+ "page": "Example/S0011/Q.1",
+ "contents": "{{#ask: [[Category:S0011]] |?Has text |limit=0 |link=none |format=table |intro=with [[intro parameter]] {{#info:intro bubble}} |outro=with [[outro parameter]] {{#info:outro bubble}} }}",
+ "message-cache": "clear"
+ },
+ {
+ "page": "Example/S0011/Q.2",
+ "contents": "{{#ask: [[Category:S0011]] |?Has text |limit=0 |link=none |format=table |intro=[[File:Foo.png|link=Bar]] }}",
+ "message-cache": "clear"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (further results)",
+ "subject": "Example/S0011/Q.1",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_MDAT",
+ "_SKEY",
+ "_ASK"
+ ],
+ "propertyValues": []
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "-5B-5BCategory%3AS0011-5D-5D%2F-3FHas-20text&amp;mainlabel=&amp;offset=0&amp;format=table&amp;link=none&amp;intro=with%20%5B%5Bintro%20parameter%5D%5D%20%3Cspan%20class%3D%22smw-highlighter%22%20data-type%3D%226%22%20data-state%3D%22persistent%22%20data-title%3D%22Information%22%20title%3D%22intro%20bubble%22%3E%3Cspan%20class%3D%22smwtticon%20info%22%3E%3C%2Fspan%3E%3Cspan%20class%3D%22smwttcontent%22%3Eintro%20bubble%3C%2Fspan%3E%3C%2Fspan%3E&amp;outro=with%20%5B%5Boutro%20parameter%5D%5D%20%3Cspan%20class%3D%22smw-highlighter%22%20data-type%3D%226%22%20data-state%3D%22persistent%22%20data-title%3D%22Information%22%20title%3D%22outro%20bubble%22%3E%3Cspan%20class%3D%22smwtticon%20info%22%3E%3C%2Fspan%3E%3Cspan%20class%3D%22smwttcontent%22%3Eoutro%20bubble%3C%2Fspan%3E%3C%2Fspan%3E"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (parse [[ ... ]] as links in intro/outro)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0011-5D-5D/-3FCategory/-3FHas-20text=Text/mainlabel=/limit=100/offset=0/format=table/link=none/intro=-5B-5Bintro-parameter-5D-5D/outro=-5B-5Boutro-parameter-5D-5D",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=Intro%25parameter",
+ "class=\"new\" title=\"Intro%parameter",
+ "\">intro%parameter</a>",
+ "<td class=\"smwtype_wpg\">Example/S0011/1</td>",
+ "class=\"new\" title=\"Outro%parameter",
+ "\">outro%parameter</a>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (parse URL in intro/outro)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0011-5D-5D/-3FCategory/-3FHas-20text=Text/mainlabel=/limit=100/offset=0/format=table/link=none/intro=http:-2F-2Fexample.org-2Fintro/outro=http:-2F-2Fexample.org-2Foutro",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<a rel=\"nofollow\" class=\"external free\" href=\"http://example.org/intro\">http://example.org/intro</a>",
+ "<td class=\"smwtype_wpg\">Example/S0011/1</td>",
+ "<a rel=\"nofollow\" class=\"external free\" href=\"http://example.org/outro\">http://example.org/outro</a>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3 (parse template in intro/outro)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0011-5D-5D/-3FCategory/-3FHas-20text=Text/mainlabel=/limit=100/offset=0/format=table/link=none/intro=-7B-7BS0011-2DTemplate-7Ctest%3DS0011-intro-7D-7D/outro=-7B-7BS0011-2DTemplate-7Ctest%3DS0011-outro-7D-7D",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "S0011%intro link",
+ "class=\"new\" title=\"S0011%intro",
+ "\">S0011%intro</a>",
+ "<td class=\"smwtype_wpg\">Example/S0011/1</td>",
+ "S0011%outro link",
+ "class=\"new\" title=\"S0011%outro",
+ "\">S0011%outro</a>"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (#3196, `-3D/=` decode)",
+ "subject": "Example/S0011/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "-5B-5BCategory:S0011-5D-5D/-3FHas-20text/mainlabel%3D/offset%3D0/format%3Dtable/link%3Dnone/intro%3D-5B-5BFile:Foo.png-7Clink%3DBar-5D-5D"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0012.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0012.json
new file mode 100644
index 00000000..adea6b51
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0012.json
@@ -0,0 +1,66 @@
+{
+ "description": "Test `Special:Ask` output `#ask` image/upload (#2009, `wgContLang=en`, `wgLang=en`, `wgEnableUploads`, `wgFileExtensions`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has caption",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_FILE",
+ "page": "S0012.png",
+ "contents": {
+ "upload": {
+ "file" : "/../Fixtures/image-upload-480.png",
+ "text" : "[[Has file::{{FULLPAGENAME}}]] [[Has caption::Test file]] [[Category:S0012]]"
+ }
+ }
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (display image in table with 50px|thumb|123)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0012-5D-5D/-3FHas-20file#50px;thumb;123/mainlabel=-/offset=0/format=broadtable/link=all/headers=show",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<td class=\"Has-file smwtype_wpg\"><div class=\"thumb tright\"><div class=\"thumbinner\" style=\"width:52px;\">",
+ "S0012.png/50px-S0012.png\" width=\"50\" height=\"50\" class=\"thumbimage\"",
+ "<div class=\"thumbcaption\"><div class=\"magnify\">",
+ "class=\"internal\" title=\"Enlarge\">",
+ "</a></div>123</div>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgEnableUploads": true,
+ "wgFileExtensions": [
+ "png"
+ ],
+ "wgDefaultUserOptions": {
+ "thumbsize": 5
+ },
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_FILE": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0013.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0013.json
new file mode 100644
index 00000000..9862c886
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0013.json
@@ -0,0 +1,48 @@
+{
+ "description": "Test `Special:Browse` output preferred label (`wgContLang=en`, `wgLang=es`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "SomeProperty",
+ "contents": "[[Has type::Text]] [[Has preferred property label::Label with spaces@es]]"
+ },
+ {
+ "page": "Example/S0013/1",
+ "contents": "[[SomeProperty::abc]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 verify preferred label display",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0013/1",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ ">Label with spaces</a>&nbsp;<span title=\"SomeProperty\"><sup>ᵖ</sup>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "es",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0014.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0014.json
new file mode 100644
index 00000000..63d46336
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0014.json
@@ -0,0 +1,240 @@
+{
+ "description": "Test `Special:Browse` with special characters `%'\"&` (`wgContLang=en`, `wgLang=es` )",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/S0014/L'oéal",
+ "contents": "[[Has page::{{FULLPAGENAME}}]] [[Category:S0014]]"
+ },
+ {
+ "page": "Example/S0014/%Some@%",
+ "contents": "[[Has page::{{FULLPAGENAME}}]] [[Category:S0014]]"
+ },
+ {
+ "page": "Example/S0014/ABC(-3-)",
+ "contents": "[[Has page::{{FULLPAGENAME}}]] [[Category:S0014]]"
+ },
+ {
+ "page": "Example/S0014/\"Some\"&*^-25-20-2D",
+ "contents": "[[Has page::{{FULLPAGENAME}}]] [[Category:S0014]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "skip-on": {
+ "mediawiki": [ ">1.29.x", "MediaWiki changed sanitization from `'` to `&#039;`" ]
+ },
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0014/L'oéal",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0014-2FL%27o%C3%A9al",
+ "title=\"Example/S0014/L'oéal\">Example/S0014/L'oéal</a>",
+ "Example-2FS0014-2FL'oéal"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#0 (1.30+)",
+ "skip-on": {
+ "mediawiki": [ "<1.29.x", "MediaWiki changed sanitization from `'` to `&#039;`" ]
+ },
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0014/L'oéal",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0014-2FL%27o%C3%A9al",
+ "title=\"Example/S0014/L&#039;oéal\">Example/S0014/L'oéal</a>",
+ "Example-2FS0014-2FL&#039;oéal"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1",
+ "skip-on": {
+ "mediawiki": [ ">1.29.x", "MediaWiki changed sanitization from `'` to `&#039;`" ]
+ },
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "",
+ "request-parameters": {
+ "output": "legacy",
+ "article" : "Example/S0014/L'oéal"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0014-2FL%27o%C3%A9al",
+ "title=\"Example/S0014/L'oéal\">Example/S0014/L'oéal</a>",
+ "Example-2FS0014-2FL'oéal"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (1.30+)",
+ "skip-on": {
+ "mediawiki": [ "<1.29.x", "MediaWiki changed sanitization from `'` to `&#039;`" ]
+ },
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "",
+ "request-parameters": {
+ "output": "legacy",
+ "article" : "Example/S0014/L'oéal"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example-2FS0014-2FL%27o%C3%A9al",
+ "title=\"Example/S0014/L&#039;oéal\">Example/S0014/L'oéal</a>",
+ "Example-2FS0014-2FL&#039;oéal"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0014/%Some@%",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/S0014/%Some@%\">Example/S0014/%Some@%</a>",
+ "Example-2FS0014-2F-25Some@-25"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "",
+ "request-parameters": {
+ "output": "legacy",
+ "article" : "Example/S0014/%Some@%"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/S0014/%Some@%\">Example/S0014/%Some@%</a>",
+ "Example-2FS0014-2F-25Some@-25"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#4",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0014/ABC(-3-)",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/S0014/ABC(-3-)\">Example/S0014/ABC(-3-)</a>",
+ "Example-2FS0014-2FABC(-2D3-2D)"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#5",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "",
+ "request-parameters": {
+ "output": "legacy",
+ "article" : "Example/S0014/ABC(-3-)"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "title=\"Example/S0014/ABC(-3-)\">Example/S0014/ABC(-3-)</a>",
+ "Example-2FS0014-2FABC(-2D3-2D)"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#6",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0014/\"Some\"&*^-25-20-2D",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/S0014/%22Some%22%26*%5E-25-20-2D",
+ "title=\"Example/S0014/&quot;Some&quot;&amp;*^-25-20-2D\">Example/S0014/\"Some\"&*^-25-20-2D</a>",
+ "Example-2FS0014-2F&quot;Some&quot;-26*^-2D25-2D20-2D2D"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#6",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "",
+ "request-parameters": {
+ "output": "legacy",
+ "article": "Example/S0014/\"Some\"&*^-25-20-2D"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example/S0014/%22Some%22%26*%5E-25-20-2D",
+ "title=\"Example/S0014/&quot;Some&quot;&amp;*^-25-20-2D\">Example/S0014/\"Some\"&*^-25-20-2D</a>",
+ "Example-2FS0014-2F&quot;Some&quot;-26*^-2D25-2D20-2D2D"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "es",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "skip-on": {
+ "mw-1.25.6": "Somehow the content lang is not set correctly on Travis (locally works fine)."
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0015.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0015.json
new file mode 100644
index 00000000..fb5e414e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0015.json
@@ -0,0 +1,71 @@
+{
+ "description": "Test `Special:Ask` output for `_txt` with formatted text (#..., `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0015/1",
+ "contents": "[[Has text::Test '''with text formatting''']] {{#set: Has text=Link to [[Example/S0015/1]]}} [[Category:S0015]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0015/2",
+ "contents": "[[Code::Test '''with text formatting''']] {{#set: Code=Link to [[Example/S0015/1]]}} [[Category:S0015]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (`_txt` formatting, link)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0015-5D-5D-20-5B-5BHas text%3A%3A%2B-5D-5D/-3FHas text/mainlabel=-/offset=0/format=broadtable/link=all/headers=show",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "Test <b>with text formatting</b>",
+ "Link to <a",
+ "Example/S0015/1\" title=\"Example/S0015/1\">Example/S0015/1</a>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (`_cod` formatting, link)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory%3AS0015-5D-5D-20-5B-5BCode%3A%3A%2B-5D-5D/-3FCode/mainlabel=-/offset=0/format=broadtable/link=all/headers=show",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smwpre\">Link&#160;to&#160;&#91;&#91;Example/S0015/1]]</div>",
+ "<div class=\"smwpre\">Test&#160;&#x27;&#x27;&#x27;with&#160;text&#160;formatting&#x27;&#x27;&#x27;</div>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0016.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0016.json
new file mode 100644
index 00000000..6a29e659
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0016.json
@@ -0,0 +1,128 @@
+{
+ "description": "Test `Special:Ask` to produce correct printout position for `+|...` parameters (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has monolingual text",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0016/1",
+ "contents": "[[Has monolingual text::Test@en]] [[Has monolingual text::テスト@ja]] [[Category:S0016]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (column order for printouts with additional `+|...` parameter)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0016-5D-5D/-3FHas-20monolingual-20text-7C%2Blang%3Den/-3FModification-20date/mainlabel%3D/offset%3D0/format%3Dtable/link%3Dnone",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\"><thead><th>&nbsp;</th><th class=\"Has-monolingual-text\">",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td class=\"Has-monolingual-text smwtype_txt\">Test</td>"
+ ],
+ "not-contain": [
+ "<table class=\"sortable wikitable smwtable\"><thead><th>&nbsp;</th><th class=\"Modification-date\">",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td data-sort-value=\"2457858.0750926\" class=\"Modification-date smwtype_dat\">"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (column order for mixed printout)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0016-5D-5D/-3FHas-20monolingual-20text-7C%2Blang%3Den/-3FCategory/-3FHas-20monolingual-20text-7C%2Blang%3Dja/mainlabel%3D/offset%3D0/format%3Dtable/link%3Dnone",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"Has-monolingual-text\"><a .* title=\"Property:Has monolingual text\">Has monolingual text</a></th><th class=\"Category\"><a .*>Category</a></th><th class=\"Has-monolingual-text\"><a .* title=\"Property:Has monolingual text\">Has monolingual text</a></th>",
+ "<tbody><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td class=\"Has-monolingual-text smwtype_txt\">Test</td><td class=\"Category smwtype_wpg\">Category:S0016</td><td class=\"Has-monolingual-text smwtype_txt\">テスト</td></tr></tbody>"
+ ],
+ "not-contain": [
+ "<tbody><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td class=\"Has-monolingual-text smwtype_txt\">Test</td><td class=\"Has-monolingual-text smwtype_txt\">テスト</td></tr></tbody>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (column order for mixed printout)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": [],
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "searchlabel": "some..."
+ },
+ "q": "[[Category:S0016]]",
+ "po": "?Has monolingual text|+lang=en|?Category|?Has monolingual text|+lang=ja"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"Has-monolingual-text\"><a .* title=\"Property:Has monolingual text\">Has monolingual text</a></th><th class=\"Category\"><a .*>Category</a></th><th class=\"Has-monolingual-text\"><a .* title=\"Property:Has monolingual text\">Has monolingual text</a></th>",
+ "<tbody><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td class=\"Has-monolingual-text smwtype_txt\">Test</td><td class=\"Category smwtype_wpg\">Category:S0016</td><td class=\"Has-monolingual-text smwtype_txt\">テスト</td></tr></tbody>"
+ ],
+ "not-contain": [
+ "<tbody><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td class=\"Has-monolingual-text smwtype_txt\">Test</td><td class=\"Has-monolingual-text smwtype_txt\">テスト</td></tr></tbody>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3 (column order for mixed printout)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": [],
+ "request-parameters": {
+ "p": [
+ "link=none",
+ "limit=10",
+ "offset=0",
+ "mainlabel=",
+ "searchlabel=some..."
+ ],
+ "q": "[[Category:S0016]]",
+ "po": "?Has monolingual text|+lang=en|?Category|?Has monolingual text|+lang=ja"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<th class=\"Has-monolingual-text\"><a .* title=\"Property:Has monolingual text\">Has monolingual text</a></th><th class=\"Category\"><a .*>Category</a></th><th class=\"Has-monolingual-text\"><a .* title=\"Property:Has monolingual text\">Has monolingual text</a></th>",
+ "<tbody><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td class=\"Has-monolingual-text smwtype_txt\">Test</td><td class=\"Category smwtype_wpg\">Category:S0016</td><td class=\"Has-monolingual-text smwtype_txt\">テスト</td></tr></tbody>"
+ ],
+ "not-contain": [
+ "<tbody><tr data-row-number=\"1\" class=\"row-odd\"><td class=\"smwtype_wpg\">Example/S0016/1</td><td class=\"Has-monolingual-text smwtype_txt\">Test</td><td class=\"Has-monolingual-text smwtype_txt\">テスト</td></tr></tbody>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0017.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0017.json
new file mode 100644
index 00000000..ef55a15d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0017.json
@@ -0,0 +1,79 @@
+{
+ "description": "Test `Special:Types` (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has monolingual text",
+ "contents": "[[Has type::Monolingual text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Types",
+ "query-parameters": "",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div id=\"smw-types\" class=\"smw-tabs smw-types\"><input id=\"tab-smw-type-list\" class=\"nav-tab\" type=\"radio\" name=\"types\" checked=\"\"/>",
+ "<p class=\"plainlinks smw-types-intro\">"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (Monolingual text)",
+ "special-page": {
+ "page": "Types",
+ "query-parameters": "Monolingual text",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-breadcrumb-link\"><span class=\"smw-breadcrumb-arrow-right\">",
+ "<a href=\".*Has_monolingual_text\" title=\".*Has monolingual text\">"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (Foobar, unknown)",
+ "special-page": {
+ "page": "Types",
+ "query-parameters": "Foobar",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"plainlinks smw-type-unknown\">"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0018.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0018.json
new file mode 100644
index 00000000..6491a23c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0018.json
@@ -0,0 +1,93 @@
+{
+ "description": "Test `Special:Ask` common output (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0018/1",
+ "contents": "[[Has page::123]] [[Category:S0018]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (noscript)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": [],
+ "request-parameters": {}
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div id=\"ask-status\" class=\"smw-ask-status plainlinks\"><noscript><div class=\"smw-callout smw-callout-error\">"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (@see #3542, `format= table`)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0018-5D-5D/-3FHas-20page/mainlabel%3D/offset%3D0/format%3D-20table",
+ "request-parameters": {}
+ },
+ "assert-output": {
+ "to-contain": [
+ "{{#ask: [[Category:S0018]]",
+ " |?Has page",
+ " |format=table",
+ " |limit=50",
+ " |offset=0",
+ " |sort=",
+ " |order=asc",
+ " |mainlabel=",
+ "}}"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (`format=TABLE`)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0018-5D-5D/-3FHas-20page/mainlabel%3D/offset%3D0/format%3DTABLE",
+ "request-parameters": {}
+ },
+ "assert-output": {
+ "to-contain": [
+ "{{#ask: [[Category:S0018]]",
+ " |?Has page",
+ " |format=table",
+ " |limit=50",
+ " |offset=0",
+ " |sort=",
+ " |order=asc",
+ " |mainlabel=",
+ "}}"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgNamespace": "http://example.org/id/",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0019.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0019.json
new file mode 100644
index 00000000..324ee61e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0019.json
@@ -0,0 +1,40 @@
+{
+ "description": "Test output of `Special:WantedProperties` on unapproved property (`wgContLang=en`, `wgLang=en`, `smwgCreateProtectionRight`)",
+ "setup": [
+ {
+ "page": "Example/S0019/1",
+ "contents": "[[SomeWantedProperty::123]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 restricted property causes unapproved listing",
+ "special-page": {
+ "page": "WantedProperties",
+ "query-parameters": [],
+ "request-parameters": {
+ "filter": "unapprove"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<li><a .*SomeWantedProperty&amp;action=view\" .*SomeWantedProperty</a> (1 use)</li>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgCreateProtectionRight": "foo"
+ },
+ "meta": {
+ "skip-on": {
+ "sqlite": "Returns a `database is locked`"
+ },
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0020.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0020.json
new file mode 100644
index 00000000..24534f34
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0020.json
@@ -0,0 +1,121 @@
+{
+ "description": "Test `Special:Ask` with `format=json` output (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0020/1",
+ "contents": "[[Has text::Some example]] [[Category:S0020]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0020/2",
+ "contents": "[[Has number::123]] [[Has number::345]] [[Category:S0020]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "prettyprint": false,
+ "unescape": true,
+ "format": "json"
+ },
+ "q": "[[Category:S0020]]",
+ "po": "?Has text|?Has number"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/s-0020.0.txt"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 `type=simple`",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "type": "simple",
+ "prettyprint": false,
+ "unescape": true,
+ "format": "json"
+ },
+ "q": "[[Category:S0020]]",
+ "po": "?Has text|?Has number"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/s-0020.1.txt"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 `type=simple`, `mainlabel=-`",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "-",
+ "type": "simple",
+ "prettyprint": false,
+ "unescape": true,
+ "format": "json"
+ },
+ "q": "[[Category:S0020]]",
+ "po": "?Has text|?Has number"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/s-0020.2.txt"
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0021.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0021.json
new file mode 100644
index 00000000..70572079
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0021.json
@@ -0,0 +1,81 @@
+{
+ "description": "Test `format=table` on `Special:Ask` with `headers=plain` (#2702, `wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has extra text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/S0021/1",
+ "contents": "[[Has extra text::S0021]]"
+ },
+ {
+ "page": "Example/S0021/2",
+ "contents": "[[Has extra text::S0021]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 with headers",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "limit": "10",
+ "offset": "0",
+ "headers": "",
+ "format": "table"
+ },
+ "q": "[[Has extra text::S0021]]",
+ "po": "?Has extra text=Modified <i>label</i> for text"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<thead><th>&nbsp;</th><th class=\"Modified-label-for-text\"><a href=.* title=\"Property:Has extra text\">Modified <i>label</i> for text</a></th></thead>",
+ "<a href=.* title=\"Example/S0021/1\">Example/S0021/1</a>",
+ "<a href=.* title=\"Example/S0021/2\">Example/S0021/2</a>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 with headers plain",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "limit": "10",
+ "offset": "0",
+ "headers": "plain",
+ "format": "table"
+ },
+ "q": "[[Has extra text::S0021]]",
+ "po": "?Has extra text=Modified <i>label</i> for text"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<thead><th>&nbsp;</th><th class=\"Modified-label-for-text\">Modified <i>label</i> for text</th></thead>",
+ "<a href=.* title=\"Example/S0021/1\">Example/S0021/1</a>",
+ "<a href=.* title=\"Example/S0021/2\">Example/S0021/2</a>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0022.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0022.json
new file mode 100644
index 00000000..946ef38d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0022.json
@@ -0,0 +1,248 @@
+{
+ "description": "Test `format=csv` output via `Special:Ask` (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0022/1",
+ "contents": "[[Has text::Some example]] [[Category:S0022]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0022/2",
+ "contents": "[[Has number::123]] [[Has number::345]] [[Category:S0022]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0022/3",
+ "contents": "[[Has text::ABC]] [[Has number::123]] [[Category:S0022]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "Example/S0022/4",
+ "contents": "[[Has text::DEF]] [[Has number::123]] [[Category:S0022]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 with header",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "format": "csv"
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has text|?Has number"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.0.csv"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 without header",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "headers": "hide",
+ "format": "csv"
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has text|?Has number"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.1.csv"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 mainlabel",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "-",
+ "format": "csv"
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has number|?Has text"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.2.csv"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3 merge rows with identical first column identifier",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "-",
+ "format": "csv",
+ "merge": true
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has number|?Has text"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.3.csv"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#4 valuesep, headers=hide",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "headers": "hide",
+ "valuesep": ";",
+ "format": "csv"
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has text|?Has number"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.4.csv"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#5 sep, valuesep",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "format": "csv",
+ "sep": "|",
+ "valuesep": "+"
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has number|?Has text"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.5.csv"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#6 merge rows, valuesep",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "-",
+ "format": "csv",
+ "valuesep": ";",
+ "merge": true
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has number|?Has text"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.6.csv"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#7 merge rows, valuesep, sep",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "-",
+ "format": "csv",
+ "sep": "|",
+ "valuesep": ";",
+ "merge": true
+ },
+ "q": "[[Category:S0022]]",
+ "po": "?Has number|?Has text"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0022.7.csv"
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0023.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0023.json
new file mode 100644
index 00000000..b1e2a9a2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0023.json
@@ -0,0 +1,44 @@
+{
+ "description": "Test `Special:Browse` output category (`wgContLang=en`, `wgLang=en`)",
+ "setup": [
+ {
+ "page": "Example/S0023/1",
+ "contents": "[[Category:S0023]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (category singular display)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0023/1",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<div class=\"smw-table-cell smwb-cell smwb-prophead\"><a href=.*>Category</a></div>",
+ "<div class=\"smw-table-cell smwb-cell smwb-propval\"><span class=\"smwb-value\"><a href=.*>S0023</a></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0024.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0024.json
new file mode 100644
index 00000000..effac312
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0024.json
@@ -0,0 +1,49 @@
+{
+ "description": "Test `Special:Browse` with compact links (`smwgCompactLinkSupport`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/S0024/L'oéal",
+ "contents": "[[Has page::{{FULLPAGENAME}}]] [[Category:S0024]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "cl:OkV4YW1wbGUtMkZTMDAyNC0yRkwnb8OpYWw",
+ "request-parameters": {
+ "output": "legacy"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwbrowse\"><a href=.*cl:OkV4YW1wbGUtMkZTMDAyNC0yRkwnb8OpYWw\" title=\"Special:Browse/cl:OkV4YW1wbGUtMkZTMDAyNC0yRkwnb8OpYWw\">+</a></span>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgCompactLinkSupport": true,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0025.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0025.json
new file mode 100644
index 00000000..42cb41c2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0025.json
@@ -0,0 +1,106 @@
+{
+ "description": "Test `format=templatefile` (with `_eid`) output via `Special:Ask`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has GND",
+ "contents": "[[Has type::External identifier]] [[External formatter uri::http://d-nb.info/gnd/$1]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has name",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "BEACON",
+ "contents": {
+ "import-from": "/../Fixtures/s-0025-beacon.txt"
+ }
+ },
+ {
+ "namespace": "NS_TEMPLATE",
+ "page": "BEACON-INTRO",
+ "contents": {
+ "import-from": "/../Fixtures/s-0025-beacon-intro.txt"
+ }
+ },
+ {
+ "page": "Example/S0025/1",
+ "contents": "[[Has name::John Doe]] [[Has GND::123456789]]"
+ },
+ {
+ "page": "Example/S0025/2",
+ "contents": "[[Has name::Jane Doe]] [[Has GND::987654321]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "format": "templatefile",
+ "template": "BEACON",
+ "introtemplate": "BEACON-INTRO"
+ },
+ "q": "[[Has GND::123456789]]",
+ "po": "?Has GND=GND|?Has name=Name"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0025.0.txt"
+ }
+ }
+ },
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "format": "templatefile",
+ "template": "BEACON",
+ "introtemplate": "BEACON-INTRO"
+ },
+ "q": "[[Has GND::123456789]] OR [[Has GND::987654321]]",
+ "po": "?Has GND=GND|?Has name=Name"
+ }
+ },
+ "assert-output": {
+ "to-contain": {
+ "contents-file" : "/../Fixtures/res.s-0025.1.txt"
+ }
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0026.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0026.json
new file mode 100644
index 00000000..3cd361ec
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0026.json
@@ -0,0 +1,47 @@
+{
+ "description": "Test output from `Special:PageProperty` (with `_dat`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "S0026 date",
+ "contents": "[[Has type::Date]]"
+ },
+ {
+ "page": "Example/S0026/1",
+ "contents": "[[S0026 date::1 Jan 1970]]"
+ },
+ {
+ "page": "Example/S0026/2",
+ "contents": "[[S0026 date::2 Dec 2100 12:12:12]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "PageProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "type": "S0026 date"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<li>1 January 1970&#160;&#160;<span class=\"smwsearch\"><a href=\".*:S0026-20date/1-20January-201970\" title=\"1 January 1970\">+</a></span></li>",
+ "<li>2 December 2100 12:12:12&#160;&#160;<span class=\"smwsearch\"><a href=\".*:S0026-20date/2-20December-202100-2012:12:12\" title=\"2 December 2100 12:12:12\">+</a></span></li>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0027.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0027.json
new file mode 100644
index 00000000..1cca69dd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0027.json
@@ -0,0 +1,179 @@
+{
+ "description": "Test `format=feed` output via `Special:Ask` (`wgEnableUploads`, `wgFileExtensions`, `wgRestrictDisplayTitle`)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has number",
+ "contents": "[[Has type::Number]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "S0027/1",
+ "contents": "[[Has text::Some example]] [[Category:S0027]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "S0027/2",
+ "contents": "[[Has number::123]] [[Has number::345]] [[Category:S0027]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "S0027/3",
+ "contents": "[[Has text::ABC]] [[Has number::123]] [[Category:S0027]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "S0027/4",
+ "contents": "[[Has text::DEF]] [[Has number::123]] {{DISPLAYTITLE:Uses different title}} [[Category:S0027]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "S0027/Q.1",
+ "contents": "{{#ask: [[Category:S0027]] |format=feed |type=atom |limit=10 |searchlabel=feed output }}"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "S0027/Q.2",
+ "contents": "{{#ask: [[Category:S0027]] |format=feed |type=atom |limit=10 |offset=3 |searchlabel=feed output }}"
+ },
+ {
+ "namespace": "NS_FILE",
+ "page": "S0027.png",
+ "contents": {
+ "upload": {
+ "file" : "/../Fixtures/image-upload-480.png",
+ "text" : "[[Has file::File:S0027.png]] [[Has caption::Test file]] [[Category:S0027]]"
+ }
+ }
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 with header",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "format": "feed"
+ },
+ "q": "[[Category:S0027]]",
+ "po": "?Has text|?Has number"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<title>S0027/1</title>",
+ "<title>S0027/2</title>",
+ "<title>S0027/3</title>",
+ "<title>Uses different title</title>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (file)",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "format": "feed"
+ },
+ "q": "[[Has file::+]] [[Category:S0027]]",
+ "po": "?Has file|?Has caption"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<title>File:S0027.png</title>",
+ "a href=.*File:S0027.png",
+ "img alt=&quot;File:S0027.png"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (file, link=none)",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "format": "feed"
+ },
+ "q": "[[Has file::+]] [[Category:S0027]]",
+ "po": "?Has file|?Has caption"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<title>File:S0027.png</title>",
+ "File:S0027.png",
+ "Test file"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#3 (verify link, correct 0 offset)",
+ "subject": "S0027/Q.1",
+ "assert-output": {
+ "to-contain": [
+ "-5B-5BCategory:S0027-5D-5D/mainlabel=/limit=10/order=desc/sort=/offset=0/format=feed/searchlabel=feed-20output/type=atom"
+ ]
+ }
+ },
+ {
+ "type": "parser",
+ "about": "#4 (verify link)",
+ "subject": "S0027/Q.2",
+ "assert-output": {
+ "to-contain": [
+ "-5B-5BCategory:S0027-5D-5D/mainlabel=/offset=3/limit=10/order=desc/sort=/format=feed/searchlabel=feed-20output/type=atom"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgCompactLinkSupport": false,
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "wgEnableUploads": true,
+ "wgFileExtensions": [
+ "png"
+ ],
+ "wgDefaultUserOptions": {
+ "thumbsize": 5
+ },
+ "wgRestrictDisplayTitle": false,
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "NS_FILE": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0028.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0028.json
new file mode 100644
index 00000000..43ace00c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0028.json
@@ -0,0 +1,94 @@
+{
+ "description": "Test `Special:Browse` limited value list",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has text",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Example/S0028/1",
+ "contents": "[[Has text::S1]], [[Has text::S2]], [[Has text::S3]], [[Has text::S4]], [[Has text::S5]], [[Has text::S6]]"
+ },
+ {
+ "page": "Example/S0028/2",
+ "contents": "[[Has page::Example/S0028/5]]"
+ },
+ {
+ "page": "Example/S0028/3",
+ "contents": "[[Has page::Example/S0028/5]]"
+ },
+ {
+ "page": "Example/S0028/4",
+ "contents": "[[Has page::Example/S0028/5]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (limited outgoing value list)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0028/1",
+ "request-parameters": {
+ "output": "legacy",
+ "valuelistlimit-out": 5
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-value\">S1",
+ "<span class=\"smwb-value\">S2",
+ "<span class=\"smwb-value\">S3",
+ "<span class=\"smwb-value\">S4",
+ "<span class=\"smwb-value\">S5"
+ ],
+ "not-contain": [
+ "<span class=\"smwb-value\">S6"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (limited incoming value list)",
+ "special-page": {
+ "page": "Browse",
+ "query-parameters": "Example/S0028/5",
+ "request-parameters": {
+ "output": "legacy",
+ "valuelistlimit-in": 3
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<span class=\"smwb-ivalue\"><a href=\".*/Example/S0028/2\"",
+ "<span class=\"smwb-ivalue\"><a href=\".*/Example/S0028/3\""
+ ],
+ "not-contain": [
+ "<span class=\"smwb-ivalue\"><a href=\".*/Example/S0028/4\""
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0029.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0029.json
new file mode 100644
index 00000000..41525ec3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0029.json
@@ -0,0 +1,185 @@
+{
+ "description": "Test `Special:Ask` output on `mainlabel=.../?#...`, `format=table`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/S0029/1",
+ "contents": "[[Has page::123]] [[Category:S0029]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (?#, empty mainlabel)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F-23/mainlabel%3D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th>&nbsp;</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/S0029/1\" title=\"Example/S0029/1\">Example/S0029/1</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#0.1 (?, empty mainlabel)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F/mainlabel%3D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th>&nbsp;</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/S0029/1\" title=\"Example/S0029/1\">Example/S0029/1</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (?#, mainlabel=-, output the same as in #0)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F-23/mainlabel%3D-2D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th>&nbsp;</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/S0029/1\" title=\"Example/S0029/1\">Example/S0029/1</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (?#, mainlabel=FOO, ?# takes precedence over mainlabel, same output as in #0)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F-23/mainlabel%3DFOO/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th>&nbsp;</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"smwtype_wpg\"><a href=.*Example/S0029/1\" title=\"Example/S0029/1\">Example/S0029/1</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#3 (?#- forces plain output, empty mainlabel)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F-23-2D/mainlabel%3D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th>&nbsp;</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"smwtype_wpg\">Example/S0029/1</td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#4 (?#=Foo, empty mainlabel)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F-23%3DFoo/mainlabel%3D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th class=\"Foo\">Foo</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"Foo smwtype_wpg\"><a href=.*Example/S0029/1\" title=\"Example/S0029/1\">Example/S0029/1</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#4.1 (?=Foo, empty mainlabel)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F%3DFoo/mainlabel%3D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th class=\"Foo\">Foo</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"Foo smwtype_wpg\"><a href=.*Example/S0029/1\" title=\"Example/S0029/1\">Example/S0029/1</a></td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#5 (?#=Foo#- forces plain output, empty mainlabel)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F-23%3DFoo-23-2D/mainlabel%3D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th class=\"Foo\">Foo</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"Foo smwtype_wpg\">Example/S0029/1</td>"
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#6 (?#=Foo#- forces plain output, mainlabel=-, same output as in #5)",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BCategory:S0029-5D-5D/-3FHas-20page/-3F-23%3DFoo-23-2D/mainlabel%3D-2D/offset%3D0/format%3Dtable",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<table class=\"sortable wikitable smwtable\">",
+ "<a href=.*Property:Has_page\" title=\"Property:Has page\">Has page</a></th><th class=\"Foo\">Foo</th>",
+ "<tr data-row-number=\"1\" class=\"row-odd\"><td class=\"Has-page smwtype_wpg\" data-sort-value=\"123\">",
+ "<td class=\"Foo smwtype_wpg\">Example/S0029/1</td>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0030.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0030.json
new file mode 100644
index 00000000..c64c37ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0030.json
@@ -0,0 +1,50 @@
+{
+ "description": "Test `Special:Concepts`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_CONCEPT",
+ "page": "S0030/1",
+ "contents": "{{#concept: [[ConceptTest::+]] |Concept with no results}}"
+ },
+ {
+ "page": "S0030/2",
+ "contents": "{{#ask: [[Concept:S0030/Unknown]] }}"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Concepts",
+ "query-parameters": "",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "<a href=\".*Concept:S0030/1\" title=\"Concept:S0030/1\">Concept:S0030/1</a>"
+ ],
+ "not-contain": [
+ "Concept:S0030/Unknown"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true,
+ "SMW_NS_CONCEPT": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0031.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0031.json
new file mode 100644
index 00000000..829a37c8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0031.json
@@ -0,0 +1,95 @@
+{
+ "description": "Test `Special:Ask` output on `?...=[[...|...]]|+index...`",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has page",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/S0031/1",
+ "contents": "[[Has page::123]] [[Category:S0031]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (#3211, label `?Has page=[[Foo|bar]]` ",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BHas-20page::123-5D-5D-20-5B-5BCategory:S0031-5D-5D/-3FHas-20page%3D-5B-5BFoo-7Cbar-5D-5D/mainlabel%3D/offset%3D0/format%3Dtable/headers%3Dplain",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "{{#ask: [[Has page::123]] [[Category:S0031]]",
+ " |?Has page=[[Foo|bar]]",
+ " |order=asc",
+ " |headers=plain",
+ " |mainlabel="
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#1 (#3211, label `?Has page=[[Foo|bar]]|+index=1` ",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": "-5B-5BHas-20page::123-5D-5D-20-5B-5BCategory:S0031-5D-5D/-3FHas-20page%3D-5B-5BFoo-7Cbar-5D-5D-7C%2Bindex%3D1/mainlabel%3D/offset%3D0/format%3Dtable/headers%3Dplain",
+ "request-parameters": []
+ },
+ "assert-output": {
+ "to-contain": [
+ "{{#ask: [[Has page::123]] [[Category:S0031]]",
+ " |?Has page=[[Foo|bar]]|+index=1",
+ " |order=asc",
+ " |headers=plain",
+ " |mainlabel="
+ ]
+ }
+ },
+ {
+ "type": "special",
+ "about": "#2 (#3211, label `?Has page=[[Foo|bar]]|+index=1` ",
+ "special-page": {
+ "page": "Ask",
+ "query-parameters": [],
+ "request-parameters": {
+ "p": {
+ "headers": "plain",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "searchlabel": ""
+ },
+ "q": "[[Has page::123]] [[Category:S0031]]",
+ "po": "?Has page=[[Foo|bar]]|+index=1"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "{{#ask: [[Has page::123]] [[Category:S0031]]",
+ " |?Has page=[[Foo|bar]]|+index=1",
+ " |order=asc",
+ " |headers=plain"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0032.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0032.json
new file mode 100644
index 00000000..dd2f11ad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0032.json
@@ -0,0 +1,65 @@
+{
+ "description": "Test `format=json` output via `Special:Ask` for `_ref_rec`/`_qty` type (#3517)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Ref prop",
+ "contents": "[[Has type::Reference]] [[Has fields::Field prop;other prop]]"
+ },
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Field prop",
+ "contents": "[[Has type::Quantity]] [[Corresponds to::1 km]]"
+ },
+ {
+ "namespace": "NS_MAIN",
+ "page": "S0032/1",
+ "contents": "[[Ref prop::123;S0032/2]] [[Category:S0032]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0",
+ "special-page": {
+ "page": "Ask",
+ "request-parameters": {
+ "p": {
+ "link": "none",
+ "limit": "10",
+ "offset": "0",
+ "mainlabel": "",
+ "prettyprint": false,
+ "unescape": true,
+ "format": "json"
+ },
+ "q": "[[Category:S0032]]",
+ "po": "?Ref prop.Field prop"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "\"chain\":\"Ref prop.Field prop\"",
+ "{\"Field prop\":[{\"value\":123,\"unit\":\"km\"}]}"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "wgLanguageCode": "en",
+ "smwgPageSpecialProperties": [
+ "_MDAT"
+ ],
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0033.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0033.json
new file mode 100644
index 00000000..ad430659
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/TestCases/s-0033.json
@@ -0,0 +1,59 @@
+{
+ "description": "Test output from `Special:SearchByProperty` to show all values for a property (#3531)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has vtext",
+ "contents": "[[Has type::Text]]"
+ },
+ {
+ "page": "Test/S0033/1",
+ "contents": "[[Has vtext::123]] [[Has vtext::456]] [[Has vtext::abc]] [[Has vtext::def]] [[Has vtext::1001]] [[Has vtext::42]]"
+ },
+ {
+ "page": "Test/S0033/2",
+ "contents": "[[Has vtext::123]] [[Has vtext::456]] [[Has vtext::abc]] [[Has vtext::def]] [[Has vtext::1001]] [[Has vtext::42]]"
+ },
+ {
+ "page": "Test/S0033/3",
+ "contents": "[[Has vtext::123]] [[Has vtext::456]] [[Has vtext::abc]] [[Has vtext::def]] [[Has vtext::1001]] [[Has vtext::42]]"
+ },
+ {
+ "page": "Test/S0033/4",
+ "contents": "[[Has vtext::123]] [[Has vtext::456]] [[Has vtext::abc]] [[Has vtext::def]] [[Has vtext::1001]] [[Has vtext::42]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "special",
+ "about": "#0 (find all values for property `Has vtext`)",
+ "special-page": {
+ "page": "SearchByProperty",
+ "query-parameters": "",
+ "request-parameters": {
+ "limit": 6,
+ "property": "Has vtext"
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "<li>1001.*</li>",
+ "<li>123.*</li>",
+ "<li>42.*</li>",
+ "<li>456.*</li>",
+ "<li>abc.*</li>",
+ "<li>def.*</ul>"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLanguageCode": "en"
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/bootstrap.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/bootstrap.json
new file mode 100644
index 00000000..02e6c956
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/bootstrap.json
@@ -0,0 +1,53 @@
+{
+ "description": "Example bootstrap test case (see https://youtu.be/7fDKjPFaTaY)",
+ "setup": [
+ {
+ "namespace": "SMW_NS_PROPERTY",
+ "page": "Has example",
+ "contents": "[[Has type::Page]]"
+ },
+ {
+ "page": "Example/Bootstrap",
+ "contents": "[[Has example::Example123]]"
+ }
+ ],
+ "tests": [
+ {
+ "type": "parser",
+ "about": "#0 (page type annotation)",
+ "subject": "Example/Bootstrap",
+ "assert-store": {
+ "semantic-data": {
+ "strictPropertyValueMatch": false,
+ "propertyCount": 3,
+ "propertyKeys": [
+ "_SKEY",
+ "_MDAT",
+ "Has example"
+ ],
+ "propertyValues": [
+ "Example123"
+ ]
+ }
+ },
+ "assert-output": {
+ "to-contain": [
+ "Example123"
+ ]
+ }
+ }
+ ],
+ "settings": {
+ "wgContLang": "en",
+ "wgLang": "en",
+ "smwgNamespacesWithSemanticLinks": {
+ "NS_MAIN": true,
+ "SMW_NS_PROPERTY": true
+ }
+ },
+ "meta": {
+ "version": "2",
+ "is-incomplete": false,
+ "debug": false
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/readmeContentsBuilder.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/readmeContentsBuilder.php
new file mode 100644
index 00000000..3e5fa40c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/readmeContentsBuilder.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+/**
+ * Build contents from a selected folder and replaces the content of the
+ * README.md from where the script was started.
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class ReadmeContentsBuilder {
+
+ /**
+ * @var string
+ */
+ CONST REPLACE_START_MARKER = '<!-- Begin of generated contents by readmeContentsBuilder.php -->';
+ CONST REPLACE_END_MARKER = '<!-- End of generated contents by readmeContentsBuilder.php -->';
+
+ /**
+ * @var array
+ */
+ private $urlLocationMap = [
+ 'TestCases' => 'https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests/phpunit/Integration/JSONScript/TestCases'
+ ];
+
+ /**
+ * @since 2.4
+ */
+ public function run() {
+
+ $file = __DIR__ . '/README.md';
+ $dateTimeUtc = new \DateTime( 'now', new \DateTimeZone( 'UTC' ) );
+
+ $replacement = self::REPLACE_START_MARKER . "\n\n";
+ $replacement .= $this->doGenerateContentFor( 'TestCases', __DIR__ . '/TestCases' );
+
+ $replacement .= "\n-- Last updated on " . $dateTimeUtc->format( 'Y-m-d' ) . " by `readmeContentsBuilder.php`". "\n";
+ $replacement .= "\n" . self::REPLACE_END_MARKER;
+
+ $contents = file_get_contents( $file );
+ $start = strpos( $contents, self::REPLACE_START_MARKER );
+ $length = strrpos( $contents, self::REPLACE_END_MARKER ) - $start + strlen( self::REPLACE_END_MARKER );
+
+ file_put_contents(
+ $file,
+ substr_replace( $contents, $replacement, $start, $length )
+ );
+ }
+
+ private function doGenerateContentFor( $title, $path ) {
+
+ $output = '';
+ $urlLocation = $this->urlLocationMap[$title];
+
+ $counter = 0;
+ $tests = 0;
+ $previousFirstKey = '';
+
+ foreach ( $this->findFilesFor( $path, 'json' ) as $key => $location ) {
+
+ if ( $previousFirstKey !== $key{0} ) {
+ $output .= "\n" . '### ' . ucfirst( $key{0} ). "\n";
+ }
+
+ $output .= '* [' . $key .'](' . $urlLocation . '/' . $key . ')';
+
+ $contents = json_decode( file_get_contents( $location ), true );
+
+ if ( $contents === null || json_last_error() !== JSON_ERROR_NONE ) {
+ continue;
+ }
+
+ if ( isset( $contents['description'] ) ) {
+ $output .= " " . $contents['description'];
+ }
+
+ if ( isset( $contents['tests'] ) ) {
+ $tests += count( $contents['tests'] );
+ }
+
+ $output .= "\n";
+ $counter++;
+ $previousFirstKey = $key{0};
+ }
+
+ return "## $title\n\n" . "Contains $counter files with a total of $tests tests:\n" . $output;
+ }
+
+ private function findFilesFor( $path, $extension ) {
+
+ $files = [];
+
+ $directoryIterator = new \RecursiveDirectoryIterator( $path );
+
+ foreach ( new \RecursiveIteratorIterator( $directoryIterator ) as $fileInfo ) {
+ if ( strtolower( substr( $fileInfo->getFilename(), -( strlen( $extension ) + 1 ) ) ) === ( '.' . $extension ) ) {
+ $files[$fileInfo->getFilename()] = $fileInfo->getPathname();
+ }
+ }
+
+ return $files;
+ }
+
+}
+
+$readmeContentsBuilder = new ReadmeContentsBuilder();
+$readmeContentsBuilder->run();
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/version2TestCaseConverter.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/version2TestCaseConverter.php
new file mode 100644
index 00000000..07744f63
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/JSONScript/version2TestCaseConverter.php
@@ -0,0 +1,222 @@
+<?php
+
+namespace SMW\Tests\Integration\JSONScript;
+
+/**
+ * @private
+ * @codeCoverageIgnore
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class Version2TestCaseConverter {
+
+ /**
+ * @var array
+ */
+ private $options = [];
+
+ /**
+ * @var string
+ */
+ private $contents = '';
+
+ /**
+ * @since 2.5
+ */
+ public function run() {
+
+ // http://php.net/manual/en/function.getopt.php
+ $this->options = getopt( '', [ "file::", "test" ] );
+
+ print "\nRunning Version2TestCaseConverter ..." . "\n\n";
+
+ foreach ( $this->findFilesFor( __DIR__ . '/Fixtures', 'json' ) as $file => $location ) {
+ $this->readAndConvertFile( $file, $location );
+ }
+ }
+
+ private function readAndConvertFile( $file, $location ) {
+
+ if ( isset( $this->options['file'] ) && $this->options['file'] !== $file ) {
+ return print "Skipping {$file} because it doesn't match " . $this->options['file'] . "\n";
+ }
+
+ $this->contents = json_decode( file_get_contents( $location ), true );
+
+ if ( isset( $this->contents['meta']['version'] ) && $this->contents['meta']['version'] === '2' ) {
+ // return print "Skipping {$file} because it has already been tagged with version 2.\n";
+ }
+
+ // $contents = $this->replaceSpaceIndent(
+ // $this->doConvertToVersion2()
+ // );
+
+ $contents = $this->replaceSpaceIndent(
+ $this->doConvertToVersion2Assert()
+ );
+
+ if ( !isset( $this->options['test'] ) ) {
+ file_put_contents( $location, $contents );
+ print "{$file} was converted to version 2.\n";
+ } else {
+ print $contents;
+ }
+ }
+
+ private function replaceSpaceIndent( $contents ) {
+
+ // Change the four-space indent to a tab indent
+ $contents = str_replace( "\n ", "\n\t", $contents );
+
+ while ( strpos( $contents, "\t " ) !== false ) {
+ $contents = str_replace( "\t ", "\t\t", $contents );
+ }
+
+ return $contents;
+ }
+
+ private function doConvertToVersion2Assert() {
+
+ $contents = $this->contents;
+
+ foreach ( $contents['tests'] as $key => $value ) {
+
+ if ( isset( $value['store'] ) ) {
+ $value['assert-store'] = $value['store'];
+ unset( $value['store'] );
+ }
+
+ if ( isset( $value['expected-output'] ) ) {
+ $value['assert-output'] = $value['expected-output'];
+ unset( $value['expected-output'] );
+ }
+
+ $contents['tests'][$key] = $value;
+ }
+
+ foreach ( $contents['setup'] as $key => $value ) {
+
+ if ( isset( $value['name'] ) ) {
+ $value['page'] = $value['name'];
+ unset( $value['name'] );
+ }
+
+ if ( isset( $value['contents'] ) ) {
+ $v = $value['contents'];
+ unset( $value['contents'] );
+ $value['contents'] = $v;
+ }
+
+ $contents['setup'][$key] = $value;
+ }
+
+ return json_encode( $contents, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
+ }
+
+ private function doConvertToVersion2() {
+
+ $setup = [];
+ $tests = [];
+
+ // Replace and accordance with the new Version 2 structure
+ $this->findAndReplaceEntity( 'properties', $setup );
+ $this->findAndReplaceEntity( 'subjects', $setup );
+
+ // Replace and accordance with the new Version 2 structure
+ $this->findAndReplaceTestCases( 'format-testcases', 'format', $tests );
+ $this->findAndReplaceTestCases( 'parser-testcases', 'parser', $tests );
+ $this->findAndReplaceTestCases( 'rdf-testcases', 'rdf', $tests );
+ $this->findAndReplaceTestCases( 'special-testcases', 'special', $tests );
+ $this->findAndReplaceTestCases( 'query-testcases', 'query', $tests );
+ $this->findAndReplaceTestCases( 'concept-testcases', 'concept', $tests );
+
+ // Reorder
+ $contents = [
+ 'description' => $this->contents['description'],
+ 'setup' => $setup,
+ 'beforeTest' => []
+ ];
+
+ if ( isset( $this->contents['maintenance-run'] ) ) {
+ $contents['beforeTest']['maintenance-run'] = $this->contents['maintenance-run'];
+ }
+
+ if ( isset( $this->contents['job-run'] ) ) {
+ $contents['beforeTest']['job-run'] = $this->contents['job-run'];
+ }
+
+ if ( $contents['beforeTest'] === [] ) {
+ unset( $contents['beforeTest'] );
+ }
+
+ $contents['tests'] = $tests;
+ $contents['settings'] = $this->contents['settings'];
+ $contents['meta'] = $this->contents['meta'];
+ $contents['meta']['version'] = '2';
+
+ return json_encode( $contents, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
+ }
+
+ private function findAndReplaceEntity( $name, &$entities ) {
+
+ if ( !isset( $this->contents[$name] ) || $this->contents[$name] === [] ) {
+ return;
+ }
+
+ foreach ( $this->contents[$name] as $values ) {
+
+ $entity = [];
+
+ if ( $name === 'properties' ) {
+ $entity['namespace'] = "SMW_NS_PROPERTY";
+ }
+
+ foreach ( $values as $key => $value ) {
+ $entity[$key] = $value;
+ }
+
+ $entities[] = $entity;
+ }
+ }
+
+ private function findAndReplaceTestCases( $name, $type, &$tests ) {
+
+ if ( !isset( $this->contents[$name] ) || $this->contents[$name] === [] ) {
+ return;
+ }
+
+ foreach ( $this->contents[$name] as $values ) {
+
+ $case = [];
+ $case['type'] = $type;
+
+ foreach ( $values as $key => $value ) {
+ $case[$key] = $value;
+ }
+
+ $tests[] = $case;
+ }
+ }
+
+ private function findFilesFor( $path, $extension ) {
+
+ $files = [];
+
+ $directoryIterator = new \RecursiveDirectoryIterator( $path );
+
+ foreach ( new \RecursiveIteratorIterator( $directoryIterator ) as $fileInfo ) {
+ if ( strtolower( substr( $fileInfo->getFilename(), -( strlen( $extension ) + 1 ) ) ) === ( '.' . $extension ) ) {
+ $files[$fileInfo->getFilename()] = $fileInfo->getPathname();
+ }
+ }
+
+ return $files;
+ }
+
+}
+
+$version2TestCaseConverter = new Version2TestCaseConverter();
+$version2TestCaseConverter->run();
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/en.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/en.json
new file mode 100644
index 00000000..e4c16798
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/en.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": []
+ },
+ "fallback_language": false,
+ "datatype":{
+ "labels": {},
+ "aliases": {}
+ },
+ "property":{
+ "labels": {},
+ "aliases": {}
+ },
+ "namespace": {
+ "labels": [],
+ "aliases": []
+ },
+ "date": {
+ "precision": [],
+ "format": [],
+ "months": [],
+ "days": []
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-fallback.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-fallback.json
new file mode 100644
index 00000000..414602d6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-fallback.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": []
+ },
+ "fallback_language": false,
+ "datatype":{
+ "labels": {
+ "dataTypeLabels-fallback": "bar"
+ },
+ "aliases": {
+ "dataTypeAliases-fallback": "bar"
+ }
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-partial.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-partial.json
new file mode 100644
index 00000000..c69825d6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/Fixtures/foo-partial.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": []
+ },
+ "fallback_language": "foo-fallback",
+ "datatype": {
+ "labels": {
+ "dataTypeLabels-partial": "bar"
+ }
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/LanguageContentTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/LanguageContentTest.php
new file mode 100644
index 00000000..9e49a224
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/LanguageContentTest.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace SMW\Tests\Integration\Lang;
+
+use SMW\Lang\Lang;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class LanguageContent extends \PHPUnit_Framework_TestCase {
+
+ protected function tearDown() {
+ Lang::clear();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider canonicalPropertyAliasesProvider
+ */
+ public function testGetCanonicalPropertyAliases( $languageCode, $canonicalMatch, $aliasMatch, $expected ) {
+
+ $lang = Lang::getInstance()->fetch(
+ $languageCode
+ );
+
+ $canonicalPropertyAliases = $lang->getCanonicalPropertyAliases();
+
+ $this->assertEquals(
+ $expected,
+ $canonicalPropertyAliases[$canonicalMatch]
+ );
+ }
+
+ /**
+ * @dataProvider canonicalPropertyAliasesProvider
+ */
+ public function testGetPropertyAliases( $languageCode, $canonicalMatch, $aliasMatch, $expected ) {
+
+ $lang = Lang::getInstance()->fetch(
+ $languageCode
+ );
+
+ $propertyAliases = $lang->getPropertyAliases();
+
+ $this->assertEquals(
+ $expected,
+ $propertyAliases[$aliasMatch]
+ );
+ }
+
+ /**
+ * @dataProvider canonicalPropertyLabelsProvider
+ */
+ public function testGetCanonicalPropertyLabels( $languageCode, $aliasMatch, $expected ) {
+
+ $lang = Lang::getInstance()->fetch(
+ $languageCode
+ );
+
+ $propertyLabels = $lang->getCanonicalPropertyLabels();
+
+ $this->assertEquals(
+ $expected,
+ $propertyLabels[$aliasMatch]
+ );
+ }
+
+ public function canonicalPropertyAliasesProvider() {
+
+ $provider[] = [
+ 'fr',
+ 'Query size',
+ 'Taille de la requête',
+ '_ASKSI'
+ ];
+
+ return $provider;
+ }
+
+ public function canonicalPropertyLabelsProvider() {
+
+ $provider[] = [
+ 'fr',
+ 'Boolean',
+ '_boo'
+ ];
+
+ $provider[] = [
+ 'en',
+ 'Float',
+ '_num'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/PartialLanguageFallbackTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/PartialLanguageFallbackTest.php
new file mode 100644
index 00000000..fd72660d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Lang/PartialLanguageFallbackTest.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace SMW\Tests\Integration\Lang;
+
+use SMW\Lang\FallbackFinder;
+use SMW\Lang\JsonContentsFileReader;
+use SMW\Lang\Lang;
+use SMW\Lang\LanguageContents;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PartialLanguageFallback extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ JsonContentsFileReader::clear();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ JsonContentsFileReader::clear();
+
+ parent::tearDown();
+ }
+
+ public function testDeclarationsLoadedPartiallyFromFallback() {
+
+ $JsonContentsFileReader = new JsonContentsFileReader(
+ null,
+ __DIR__ . '/Fixtures'
+ );
+
+ $languageContents = new LanguageContents(
+ $JsonContentsFileReader,
+ new FallbackFinder( $JsonContentsFileReader )
+ );
+
+ $lang = new Lang(
+ $languageContents
+ );
+
+ $lang = $lang->fetch( 'foo-partial' );
+
+ // Loaded from foo-partial.json
+ $this->assertEquals(
+ [
+ 'dataTypeLabels-partial' => 'bar'
+ ],
+ $lang->getDatatypeLabels()
+ );
+
+ // foo-partial.json doesn't contain a `dataTypeAliases` declaration and is
+ // only available in its fallback (foo-fallback.json)
+ $this->assertEquals(
+ [
+ 'dataTypeAliases-fallback' => 'bar'
+ ],
+ $lang->getDatatypeAliases()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/Fixtures/test-import-19.7.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/Fixtures/test-import-19.7.xml
new file mode 100644
index 00000000..1cd60afe
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/Fixtures/test-import-19.7.xml
@@ -0,0 +1,270 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Property:Has annotation uri</title>
+ <ns>102</ns>
+ <id>503</id>
+ <sha1>ifvt9xhpsfkv04ehcnhpw3i88s0fsb8</sha1>
+ <revision>
+ <id>1342</id>
+ <timestamp>2014-03-29T16:51:25Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="53">[[Has type::Annotation URI]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has boolean</title>
+ <ns>102</ns>
+ <id>502</id>
+ <sha1>l3b3eelfib1em61uurletnc4kb1xlzh</sha1>
+ <revision>
+ <id>1338</id>
+ <timestamp>2014-03-29T16:47:13Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Boolean]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="46">[[Has type::Boolean]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has date</title>
+ <ns>102</ns>
+ <id>14</id>
+ <sha1>473nf5knraq99k8zsrg6z7o3812tu61</sha1>
+ <revision>
+ <id>1330</id>
+ <timestamp>2014-03-29T16:38:59Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Date]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has email</title>
+ <ns>102</ns>
+ <id>500</id>
+ <sha1>9puenjhr9dntyg9obgtwhvaenn98rav</sha1>
+ <revision>
+ <id>1334</id>
+ <timestamp>2014-03-29T16:42:38Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Email]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="44">[[Has type::Email]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has number</title>
+ <ns>102</ns>
+ <id>494</id>
+ <sha1>9fqf0pft61g8qqb8qtz1i5ayr1rmu30</sha1>
+ <revision>
+ <id>1321</id>
+ <timestamp>2014-03-29T16:30:26Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Number]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="45">[[Has type::Number]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has page</title>
+ <ns>102</ns>
+ <id>489</id>
+ <sha1>4sq0eljhm3yty9cifkvel3mv646ag0y</sha1>
+ <revision>
+ <id>1319</id>
+ <timestamp>2014-03-29T16:29:46Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Page]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has quantity</title>
+ <ns>102</ns>
+ <id>495</id>
+ <sha1>1ulyevjgdofvfrp7b6b17n7p0p6oy4w</sha1>
+ <revision>
+ <id>1323</id>
+ <timestamp>2014-03-29T16:34:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="219">[[Has type::Quantity]] [[Category:Lorem ipsum]]
+
+* [[Corresponds to::1 km²]]
+* [[Corresponds to::0.38610 sq mi]]
+* [[Corresponds to::1000 m²]]
+* [[Corresponds to::247.1054 acre]]
+* [[Corresponds to::988.4215 rood]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has temperature</title>
+ <ns>102</ns>
+ <id>501</id>
+ <sha1>925639l5wc4pwdmufjgza10rstpb2oa</sha1>
+ <revision>
+ <id>1336</id>
+ <timestamp>2014-03-29T16:45:35Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Temperature]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="50">[[Has type::Temperature]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has text</title>
+ <ns>102</ns>
+ <id>491</id>
+ <sha1>qi7oxp4101tdesdm3vavpgpfn1qe68u</sha1>
+ <revision>
+ <id>1320</id>
+ <timestamp>2014-03-29T16:30:07Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Text]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has Url</title>
+ <ns>102</ns>
+ <id>499</id>
+ <sha1>1fw7q2wts7v11q1z6d31g89zorhco0i</sha1>
+ <revision>
+ <id>1332</id>
+ <timestamp>2014-03-29T16:40:28Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::URL]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="42">[[Has type::URL]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Lorem ipsum</title>
+ <ns>0</ns>
+ <id>493</id>
+ <sha1>94lztkh4kgb0mvjr87iyjfq4iv7ltlh</sha1>
+ <revision>
+ <id>1358</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="979">[[Has text::Lorem ipsum dolor sit amet consectetuer Maecenas adipiscing Pellentesque id sem]]. [[Has page::Elit Aliquam urna interdum]] morbi faucibus id tellus ipsum semper wisi. [[Has page::Platea enim hendrerit]] pellentesque consectetuer scelerisque Sed est felis felis quis. Auctor Proin In dolor id et ipsum vel at vitae ut. Praesent elit convallis Praesent aliquet pellentesque vel dolor pellentesque lacinia vitae. At tortor lacus Sed In interdum pulvinar et.
+
+[[Has number::1001]] [[Has quantity::10.25 km²]] [[Has date::1 Jan 2014]] [[Has Url::http://loremipsum.org/]] [[Has annotation uri::http://loremipsum.org/foaf.rdf]] [[Has email::Lorem@ipsum.org]] [[Has temperature::100 °C]] [[Has boolean::true]]
+
+{{#subobject:|Has number=1111|Has quantity=25 sqmi|Has date=January 4, 2010 7:00 pm|Has Url=http://example.org/some/|Has annotation uri=http://example.org/foaf.rdf|Has email=Lorem@example.org|Has temperature=100 °F|Has boolean=false}}
+
+[[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Platea enim hendrerit</title>
+ <ns>0</ns>
+ <id>498</id>
+ <sha1>4vp3ppszu168lv9f0tc9eaefvgbkv8a</sha1>
+ <revision>
+ <id>1327</id>
+ <timestamp>2014-03-29T16:36:22Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="24">[[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Elit Aliquam urna interdum</title>
+ <ns>0</ns>
+ <id>497</id>
+ <sha1>c5qjdsfni2zwsd95h59jiksolm1vjiv</sha1>
+ <revision>
+ <id>1361</id>
+ <timestamp>2014-04-04T23:00:14Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="945">[[Lorem ipsum]] dolor sit amet consectetuer Maecenas adipiscing Pellentesque id sem. [[Has text::Elit Aliquam urna interdum]] morbi faucibus id tellus ipsum semper wisi. [[Has page::Platea enim hendrerit]] pellentesque consectetuer scelerisque Sed est felis felis quis. Auctor Proin In dolor id et ipsum vel at vitae ut. Praesent elit convallis Praesent aliquet pellentesque vel dolor pellentesque lacinia vitae. At tortor lacus Sed In interdum pulvinar et.
+
+[[Has number::1001]] [[Has quantity::10.25 km²]] [[Has date::1 Jan 2014]] [[Has Url::http://loremipsum.org/]] [[Has annotation uri::http://loremipsum.org/foaf.rdf]] [[Has email::Lorem@ipsum.org]] [[Has temperature::100 °C]] [[Has boolean::true]]
+
+{{#set:|Has number=9999|Has quantity=0.25 m²|Has date=22 Jan 1714|Has Url=http://example.org/|Has annotation uri=http://example.org/foaf.rdf|Has email=Lorem@example.org|Has temperature=20 K|Has boolean=false}}
+
+[[Category: Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Lorem ipsum</title>
+ <ns>14</ns>
+ <id>496</id>
+ <sha1>sir97j6uzt9ev2uyhaz1aj4i3spogih</sha1>
+ <revision>
+ <id>1355</id>
+ <timestamp>2014-04-04T22:29:18Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="17">[[Category:Main]]</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/PopulateHashFieldTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/PopulateHashFieldTest.php
new file mode 100644
index 00000000..a75828a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/PopulateHashFieldTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace SMW\Tests\Integration\Maintenance;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 3.1
+ *
+ * @author mwjames
+ */
+class PopulateHashField extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+ private $runnerFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = TestEnvironment::getUtilityFactory()->newRunnerFactory();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testRun() {
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner(
+ 'SMW\Maintenance\PopulateHashField'
+ );
+
+ $maintenanceRunner->setQuiet();
+
+ $this->assertTrue(
+ $maintenanceRunner->run()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/RemoveDuplicateEntitiesTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/RemoveDuplicateEntitiesTest.php
new file mode 100644
index 00000000..17238a04
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/RemoveDuplicateEntitiesTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace SMW\Tests\Integration\Maintenance;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RemoveDuplicateEntitiesTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+ private $runnerFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = TestEnvironment::getUtilityFactory()->newRunnerFactory();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testRun() {
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner(
+ 'SMW\Maintenance\RemoveDuplicateEntities'
+ );
+
+ $maintenanceRunner->setQuiet();
+
+ $this->assertTrue(
+ $maintenanceRunner->run()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/SetupStoreMaintenanceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/SetupStoreMaintenanceTest.php
new file mode 100644
index 00000000..9cc9ce0b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Maintenance/SetupStoreMaintenanceTest.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Maintenance;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+
+/**
+ * @group semantic-mediawiki-integration
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SetupStoreMaintenanceTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $spyMessageReporter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = $this->testEnvironment->getUtilityFactory()->newRunnerFactory();
+ $this->titleValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newTitleValidator();
+ $this->spyMessageReporter = $this->testEnvironment->getUtilityFactory()->newSpyMessageReporter();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/Fixtures/test-import-19.7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->flushPages( $this->importedTitles );
+ parent::tearDown();
+ }
+
+ public function testSetupStore() {
+
+ $this->importedTitles = [
+ 'Category:Lorem ipsum',
+ 'Lorem ipsum',
+ 'Elit Aliquam urna interdum',
+ 'Platea enim hendrerit',
+ 'Property:Has Url',
+ 'Property:Has annotation uri',
+ 'Property:Has boolean',
+ 'Property:Has date',
+ 'Property:Has email',
+ 'Property:Has number',
+ 'Property:Has page',
+ 'Property:Has quantity',
+ 'Property:Has temperature',
+ 'Property:Has text'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\SetupStore' );
+
+ $maintenanceRunner->setMessageReporter(
+ $this->spyMessageReporter
+ );
+
+ $maintenanceRunner->setQuiet();
+ $maintenanceRunner->run();
+
+ $this->assertContains(
+ 'Database initialized completed',
+ $this->spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/ApiBrowseBySubjectDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/ApiBrowseBySubjectDBIntegrationTest.php
new file mode 100644
index 00000000..ab0fc763
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/ApiBrowseBySubjectDBIntegrationTest.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use SMW\DataValueFactory;
+use SMW\MediaWiki\Api\BrowseBySubject;
+use SMW\SerializerFactory;
+use SMW\Subobject;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\MwApiFactory;
+use SMW\Tests\Utils\SemanticDataFactory;
+
+/**
+ * @group semantic-mediawiki-integration
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ApiBrowseBySubjectDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $apiFactory;
+ private $dataValueFactory;
+ private $serializerFactory;
+ private $semanticDataFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->apiFactory = new MwApiFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->serializerFactory = new SerializerFactory();
+ $this->semanticDataFactory = new SemanticDataFactory();
+ }
+
+ public function testResultDataForEmptySemanticData() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $resultData = $this->newBrowseBySubject( __METHOD__ )->getResultData();
+
+ $this->assertInternalType(
+ 'array',
+ $resultData
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $this->serializerFactory->getDeserializerFor( $resultData['query'] )->deserialize( $resultData['query'] )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $this->newBrowseBySubject( __METHOD__, true )->getResultData()
+ );
+ }
+
+ public function testResultDataForSingleSemanticDataValueAssignment() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByText( __METHOD__, 'Bar' )
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $resultData = $this->newBrowseBySubject( __METHOD__ )->getResultData();
+
+ $this->assertInternalType(
+ 'array',
+ $resultData
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $this->serializerFactory->getDeserializerFor( $resultData['query'] )->deserialize( $resultData['query'] )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $this->newBrowseBySubject( __METHOD__, true )->getResultData()
+ );
+ }
+
+ public function testResultDataFoSubobjectExtendedSemanticData() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByText( __METHOD__, 'Bar' )
+ );
+
+ $subobject = new Subobject( $semanticData->getSubject()->getTitle() );
+ $subobject->setEmptyContainerForId( 'Foo' );
+
+ $subobject->addDataValue(
+ $this->dataValueFactory->newDataValueByText( __METHOD__, 'Bam' )
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $resultData = $this->newBrowseBySubject( __METHOD__ )->getResultData();
+
+ $this->assertInternalType(
+ 'array',
+ $resultData
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $this->serializerFactory->getDeserializerFor( $resultData['query'] )->deserialize( $resultData['query'] )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $this->newBrowseBySubject( __METHOD__, true )->getResultData()
+ );
+ }
+
+ private function newBrowseBySubject( $subject, $asRawMode = false ) {
+
+ $instance = new BrowseBySubject(
+ $this->apiFactory->newApiMain( [ 'subject' => $subject ] ),
+ 'browsebysubject'
+ );
+
+ // Went away with 1.26/1.27
+ if ( function_exists( 'setRawMode' ) && $asRawMode ) {
+ $instance->getMain()->getResult()->setRawMode();
+ }
+
+ $instance->execute();
+
+ // MW 1.25
+ return method_exists( $instance, 'getResult' ) ? $instance->getResult() : $instance;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php
new file mode 100644
index 00000000..86360952
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/FileUploadIntegrationTest.php
@@ -0,0 +1,135 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Hooks;
+
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Tests\MwDBaseUnitTestCase;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-database
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class FileUploadIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $mwHooksHandler;
+ private $fixturesFileProvider;
+ private $semanticDataValidator;
+ private $pageEditor;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+
+ $this->fixturesFileProvider = $utilityFactory->newFixturesFactory()->newFixturesFileProvider();
+ $this->semanticDataValidator = $utilityFactory->newValidatorFactory()->newSemanticDataValidator();
+ $this->pageEditor = $utilityFactory->newPageEditor();
+
+ $this->mwHooksHandler = $utilityFactory->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->testEnvironment->withConfiguration( [
+ 'smwgPageSpecialProperties' => [ '_MEDIA', '_MIME' ],
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true, NS_FILE => true ],
+ 'smwgMainCacheType' => 'hash',
+ ] );
+
+ $this->testEnvironment->withConfiguration( [
+ 'wgEnableUploads' => true,
+ 'wgFileExtensions' => [ 'txt' ],
+ 'wgVerifyMimeType' => true
+ ] );
+
+ $this->mwHooksHandler->register(
+ 'FileUpload',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'FileUpload' )
+ );
+
+ $this->mwHooksHandler->register(
+ 'InternalParseBeforeLinks',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'InternalParseBeforeLinks' )
+ );
+
+ $this->mwHooksHandler->register(
+ 'LinksUpdateConstructed',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'LinksUpdateConstructed' )
+ );
+
+ $this->getStore()->setup( false );
+ }
+
+ protected function tearDown() {
+ $this->mwHooksHandler->restoreListedHooks();
+ $this->testEnvironment->tearDown();
+
+ parent::tearDown();
+ }
+
+ public function testFileUploadForDummyTextFile() {
+ Localizer::getInstance()->clear();
+
+ $subject = new DIWikiPage( 'Foo.txt', NS_FILE );
+ $fileNS = Localizer::getInstance()->getNamespaceTextById( NS_FILE );
+
+ $dummyTextFile = $this->fixturesFileProvider->newUploadForDummyTextFile( 'Foo.txt' );
+
+ $this->assertTrue(
+ $dummyTextFile->doUpload( '[[HasFile::File:Foo.txt]]' )
+ );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $expected = [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ 'HasFile', '_MEDIA', '_MIME', '_SKEY' ],
+ 'propertyValues' => [ "$fileNS:Foo.txt", 'TEXT', 'text/plain', 'Foo.txt' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $this->getStore()->getSemanticData( $subject )
+ );
+ }
+
+ /**
+ * @depends testFileUploadForDummyTextFile
+ */
+ public function testReUploadDummyTextFileToEditFilePage() {
+
+ $subject = new DIWikiPage( 'Foo.txt', NS_FILE );
+
+ $dummyTextFile = $this->fixturesFileProvider->newUploadForDummyTextFile( 'Foo.txt' );
+ $dummyTextFile->doUpload();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->pageEditor
+ ->editPage( $subject->getTitle() )
+ ->doEdit( '[[Ichi::Maru|Kyū]]' );
+
+ // File page content is kept from the initial upload
+ $expected = [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_MEDIA', '_MIME', '_SKEY', 'Ichi' ],
+ 'propertyValues' => [ 'TEXT', 'text/plain', 'Foo.txt', 'Maru' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $this->getStore()->getSemanticData( $subject )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/InternalParseBeforeLinksIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/InternalParseBeforeLinksIntegrationTest.php
new file mode 100644
index 00000000..402a1230
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/InternalParseBeforeLinksIntegrationTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-databaseless
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class InternalParseBeforeLinksIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ private $mwHooksHandler;
+ private $parserAfterTidyHook;
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $this->mwHooksHandler = UtilityFactory::getInstance()->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->mwHooksHandler->register(
+ 'InternalParseBeforeLinks',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'InternalParseBeforeLinks' )
+ );
+ }
+
+ protected function tearDown() {
+ $this->mwHooksHandler->restoreListedHooks();
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testNonParseForInvokedMessageParse() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserData->expects( $this->never() )
+ ->method( 'getSemanticData' );
+
+ $this->applicationFactory->registerObject( 'ParserData', $parserData );
+
+ wfMessage( 'properties' )->parse();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserAfterTidyIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserAfterTidyIntegrationTest.php
new file mode 100644
index 00000000..d9810415
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserAfterTidyIntegrationTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ParserAfterTidyIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ private $mwHooksHandler;
+ private $parserAfterTidyHook;
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $this->mwHooksHandler = UtilityFactory::getInstance()->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->mwHooksHandler->register(
+ 'ParserAfterTidy',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'ParserAfterTidy' )
+ );
+ }
+
+ protected function tearDown() {
+ $this->mwHooksHandler->restoreListedHooks();
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testNonParseForInvokedMessageParse() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserData->expects( $this->never() )
+ ->method( 'getSemanticData' );
+
+ $this->applicationFactory->registerObject( 'ParserData', $parserData );
+
+ wfMessage( 'properties' )->parse();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserFirstCallInitIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserFirstCallInitIntegrationTest.php
new file mode 100644
index 00000000..faaf1c9e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/ParserFirstCallInitIntegrationTest.php
@@ -0,0 +1,190 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Hooks;
+
+use SMW\ContentParser;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParserFirstCallInitIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ private $mwHooksHandler;
+ private $parserFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment( [
+ 'smwgMainCacheType' => CACHE_NONE
+ ] );
+
+ $this->mwHooksHandler = $this->testEnvironment->getUtilityFactory()->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->parserFactory = $this->testEnvironment->getUtilityFactory()->newParserFactory();
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->mwHooksHandler->register(
+ 'ParserFirstCallInit',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'ParserFirstCallInit' )
+ );
+ }
+
+ protected function tearDown() {
+ $this->mwHooksHandler->restoreListedHooks();
+ $this->testEnvironment->tearDown();
+
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider textToParseProvider
+ */
+ public function testParseWithParserFunctionEnabled( $parserName, $text ) {
+
+ $expectedNullOutputFor = [
+ 'concept',
+ 'declare'
+ ];
+
+ $title = Title::newFromText( __METHOD__ );
+ $parser = $this->parserFactory->newFromTitle( $title );
+
+ $this->testEnvironment->addConfiguration( 'smwgQEnabled', true );
+
+ $instance = new ContentParser( $title, $parser );
+ $instance->parse( $text );
+
+ if ( in_array( $parserName, $expectedNullOutputFor ) ) {
+ return $this->assertNull(
+ $this->findSemanticataFromOutput( $instance->getOutput() )
+ );
+ }
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $this->findSemanticataFromOutput( $instance->getOutput() )
+ );
+ }
+
+ /**
+ * @dataProvider textToParseProvider
+ */
+ public function testParseWithParserFunctionDisabled( $parserName, $text ) {
+
+ $expectedNullOutputFor = [
+ 'concept',
+ 'declare',
+ 'ask',
+ 'show'
+ ];
+
+ $title = Title::newFromText( __METHOD__ );
+ $parser = $this->parserFactory->newFromTitle( $title );
+
+ $this->testEnvironment->addConfiguration( 'smwgQEnabled', false );
+
+ $instance = new ContentParser( $title, $parser );
+ $instance->parse( $text );
+
+ if ( in_array( $parserName, $expectedNullOutputFor ) ) {
+ return $this->assertNull(
+ $this->findSemanticataFromOutput( $instance->getOutput() )
+ );
+ }
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $this->findSemanticataFromOutput( $instance->getOutput() )
+ );
+ }
+
+ public function textToParseProvider() {
+
+ $provider = [];
+
+ #0 ask
+ $provider[] = [
+ 'ask',
+ '{{#ask: [[Modification date::+]]|limit=1}}'
+ ];
+
+ #1 show
+ $provider[] = [
+ 'show',
+ '{{#show: [[Foo]]|limit=1}}'
+ ];
+
+ #2 subobject
+ $provider[] = [
+ 'subobject',
+ '{{#subobject:|foo=bar|lila=lula,linda,luna|+sep=,}}'
+ ];
+
+ #3 set
+ $provider[] = [
+ 'set',
+ '{{#set:|foo=bar|lila=lula,linda,luna|+sep=,}}'
+ ];
+
+ #4 set_recurring_event
+ $provider[] = [
+ 'set_recurring_event',
+ '{{#set_recurring_event:some more tests|property=has date|' .
+ 'has title=Some recurring title|title2|has group=Events123|Events456|start=June 8, 2010|end=June 8, 2011|' .
+ 'unit=week|period=1|limit=10|duration=7200|include=March 16, 2010;March 23, 2010|+sep=;|' .
+ 'exclude=March 15, 2010;March 22, 2010|+sep=;}}'
+ ];
+
+ #5 declare
+ $provider[] = [
+ 'declare',
+ '{{#declare:population=Foo}}'
+ ];
+
+ #6 concept
+ $provider[] = [
+ 'concept',
+ '{{#concept:[[Modification date::+]]|Foo}}'
+ ];
+
+ return $provider;
+ }
+
+ private function findSemanticataFromOutput( $parserOutput ) {
+
+ if ( method_exists( $parserOutput, 'getExtensionData' ) ) {
+ return $parserOutput->getExtensionData( 'smwdata' );
+ }
+
+ return isset( $parserOutput->mSMWData ) ? $parserOutput->mSMWData : null;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/TitleMoveCompleteIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/TitleMoveCompleteIntegrationTest.php
new file mode 100644
index 00000000..37c80d3d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Hooks/TitleMoveCompleteIntegrationTest.php
@@ -0,0 +1,206 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ValueDescription;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWQuery as Query;
+use Title;
+use WikiPage;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class TitleMoveCompleteIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $mwHooksHandler;
+ private $queryResultValidator;
+ private $applicationFactory;
+ private $toBeDeleted = [];
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->queryResultValidator = $utilityFactory->newValidatorFactory()->newQueryResultValidator();
+
+ $this->mwHooksHandler = $utilityFactory->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->mwHooksHandler->register(
+ 'TitleMoveComplete',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'TitleMoveComplete' )
+ );
+
+ $this->pageCreator = $utilityFactory->newPageCreator();
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgEnabledDeferredUpdate',
+ false
+ );
+ }
+
+ protected function tearDown() {
+
+ $this->mwHooksHandler->restoreListedHooks();
+ $this->testEnvironment->tearDown();
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->toBeDeleted );
+
+ parent::tearDown();
+ }
+
+ public function testPageMoveWithCreationOfRedirectTarget() {
+
+ $oldTitle = Title::newFromText( __METHOD__ . '-old' );
+ $expectedNewTitle = Title::newFromText( __METHOD__ . '-new' );
+
+ $this->assertNull(
+ WikiPage::factory( $expectedNewTitle )->getRevision()
+ );
+
+ $this->pageCreator
+ ->createPage( $oldTitle );
+
+ $result = $this->pageCreator
+ ->getPage()
+ ->getTitle()
+ ->moveTo( $expectedNewTitle, false, 'test', true );
+ $this->assertTrue( $result );
+
+ $this->assertNotNull(
+ WikiPage::factory( $oldTitle )->getRevision()
+ );
+
+ $this->assertNotNull(
+ WikiPage::factory( $expectedNewTitle )->getRevision()
+ );
+
+ $this->toBeDeleted = [
+ $oldTitle,
+ $expectedNewTitle
+ ];
+ }
+
+ public function testPageMoveWithRemovalOfOldPage() {
+
+ // Further hooks required to ensure in-text annotations can be used for queries
+ $this->mwHooksHandler->register(
+ 'InternalParseBeforeLinks',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'InternalParseBeforeLinks' )
+ );
+
+ $this->mwHooksHandler->register(
+ 'LinksUpdateConstructed',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'LinksUpdateConstructed' )
+ );
+
+ $title = Title::newFromText( __METHOD__ . '-old' );
+ $expectedNewTitle = Title::newFromText( __METHOD__ . '-new' );
+
+ $this->assertNull(
+ WikiPage::factory( $expectedNewTitle )->getRevision()
+ );
+
+ $this->pageCreator
+ ->createPage( $title )
+ ->doEdit( '[[Has function hook test::PageCompleteMove]]' );
+
+ $this->pageCreator
+ ->getPage()
+ ->getTitle()
+ ->moveTo( $expectedNewTitle, false, 'test', false );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->assertNull(
+ WikiPage::factory( $title )->getRevision()
+ );
+
+ $this->assertNotNull(
+ WikiPage::factory( $expectedNewTitle )->getRevision()
+ );
+
+ /**
+ * @query {{#ask: [[Has function hook test::PageCompleteMove]] }}
+ */
+ $description = new SomeProperty(
+ DIProperty::newFromUserLabel( 'Has function hook test' ),
+ new ValueDescription( new DIWikiPage( 'PageCompleteMove', 0 ), null, SMW_CMP_EQ )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ true
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ // #566
+ $this->assertCount(
+ 1,
+ $queryResult->getResults()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ [ DIWikiPage::newFromTitle( $expectedNewTitle ) ],
+ $queryResult
+ );
+
+ $this->toBeDeleted = [
+ $title,
+ $expectedNewTitle
+ ];
+ }
+
+ public function testPredefinedPropertyPageIsNotMovable() {
+
+ $this->mwHooksHandler->register(
+ 'TitleIsMovable',
+ $this->mwHooksHandler->getHookRegistry()->getHandlerFor( 'TitleIsMovable' )
+ );
+
+ $title = Title::newFromText( 'Modification date', SMW_NS_PROPERTY );
+ $expectedNewTitle = Title::newFromText( __METHOD__, SMW_NS_PROPERTY );
+
+ $this->pageCreator
+ ->createPage( $title );
+
+ $this->pageCreator
+ ->getPage()
+ ->getTitle()
+ ->moveTo( $expectedNewTitle, false, 'test', true );
+
+ $this->assertNotNull(
+ WikiPage::factory( $title )->getRevision()
+ );
+
+ $this->assertNull(
+ WikiPage::factory( $expectedNewTitle )->getRevision()
+ );
+
+ $this->toBeDeleted = [
+ $title,
+ $expectedNewTitle
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/CategoryInstanceAndCategoryHierarchyTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/CategoryInstanceAndCategoryHierarchyTest.php
new file mode 100644
index 00000000..7134e273
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/CategoryInstanceAndCategoryHierarchyTest.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import;
+
+use SMW\DIProperty;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\ByPageSemanticDataFinder;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class CategoryInstanceAndCategoryHierarchyTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/'. 'Fixtures/' . 'CategoryInstanceAndCategoryHierarchyTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testCategoryHierarchies() {
+
+ $this->importedTitles = [
+ 'Category:Regression test',
+ 'Category:Regression test category',
+ 'Category:Regression test sub category',
+ 'Category:Regression test sub sub category',
+ 'CategoryInstanceAndCategoryHierarchyRegressionTest/WithSubpage',
+ 'CategoryInstanceAndCategoryHierarchyRegressionTest/WithSubpage/WithSubSubpage',
+ 'CategoryInstanceAndCategoryHierarchyRegressionTest'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $title = Title::newFromText( 'CategoryInstanceAndCategoryHierarchyRegressionTest' );
+
+ $expectedCategoryAsWikiValue = [
+ 'property' => new DIProperty( '_INST' ),
+ 'propertyValues' => [
+ 'Regression test',
+ 'Regression test category',
+ 'Regression test sub category',
+ 'Regression test sub sub category',
+ 'Category regression test'
+ ]
+ ];
+
+ $semanticDataFinder = new ByPageSemanticDataFinder;
+ $semanticDataFinder->setTitle( $title )->setStore( $this->getStore() );
+
+ $semanticDataBatches = [
+ $semanticDataFinder->fetchFromOutput(),
+ $semanticDataFinder->fetchFromStore()
+ ];
+
+ foreach ( $semanticDataBatches as $semanticData ) {
+
+ $this->semanticDataValidator->assertThatCategoriesAreSet(
+ $expectedCategoryAsWikiValue,
+ $semanticData
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/CategoryInstanceAndCategoryHierarchyTest-Mw-1-19-7.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/CategoryInstanceAndCategoryHierarchyTest-Mw-1-19-7.xml
new file mode 100644
index 00000000..45c32c47
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/CategoryInstanceAndCategoryHierarchyTest-Mw-1-19-7.xml
@@ -0,0 +1,175 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Category:Regression test</title>
+ <ns>14</ns>
+ <id>420</id>
+ <sha1>4s17yzvoj5kq6dzdmgnw7t1ukpr4tkz</sha1>
+ <revision>
+ <id>1035</id>
+ <timestamp>2014-01-31T07:30:44Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <minor/>
+ <comment>1 revision</comment>
+ <text xml:space="preserve" bytes="24">Regression test category</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Regression test category</title>
+ <ns>14</ns>
+ <id>436</id>
+ <sha1>jbu6rw2ii5g9p96hghe03cxv0jpz5cn</sha1>
+ <revision>
+ <id>1052</id>
+ <timestamp>2014-01-31T07:38:13Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Category:Regression test]]&quot;</comment>
+ <text xml:space="preserve" bytes="28">[[Category:Regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Regression test sub category</title>
+ <ns>14</ns>
+ <id>431</id>
+ <sha1>03rwhvehzgfof9pek6jnnrneqoy2iwm</sha1>
+ <revision>
+ <id>1051</id>
+ <timestamp>2014-01-31T07:37:41Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="37">[[Category:Regression test category]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Regression test sub sub category</title>
+ <ns>14</ns>
+ <id>432</id>
+ <sha1>4gttxr4kimh7dg13xhqx5fq85922n4g</sha1>
+ <revision>
+ <id>1039</id>
+ <timestamp>2014-01-31T07:30:45Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <minor/>
+ <comment>1 revision</comment>
+ <text xml:space="preserve" bytes="41">[[Category:Regression test sub category]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>CategoryInstanceAndCategoryHierarchyRegressionTest/WithSubpage</title>
+ <ns>0</ns>
+ <id>434</id>
+ <sha1>lyd8hlp26so4fwzfqr2lofdz3n6wihy</sha1>
+ <revision>
+ <id>1047</id>
+ <timestamp>2014-01-31T07:32:12Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <minor/>
+ <comment>Tester moved page [[CategoryAndCategoryHierarchyRegressionTest/WithSubpage]] to [[CategoryInstanceAndCategoryHierarchyRegressionTest/WithSubpage]] without leaving a redirect</comment>
+ <text xml:space="preserve" bytes="79">[[Category:Regression test sub category]] [[Category:Category regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>CategoryInstanceAndCategoryHierarchyRegressionTest/WithSubpage/WithSubSubpage</title>
+ <ns>0</ns>
+ <id>435</id>
+ <sha1>55b8se56m3zu8twdemk2m5ii2o7p34w</sha1>
+ <revision>
+ <id>1048</id>
+ <timestamp>2014-01-31T07:32:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <minor/>
+ <comment>Tester moved page [[CategoryAndCategoryHierarchyRegressionTest/WithSubpage/WithSubSubpage]] to [[CategoryInstanceAndCategoryHierarchyRegressionTest/WithSubpage/WithSubSubpage]] without leaving a redirect</comment>
+ <text xml:space="preserve" bytes="83">[[Category:Regression test sub sub category]] [[Category:Category regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>CategoryInstanceAndCategoryHierarchyRegressionTest</title>
+ <ns>0</ns>
+ <id>433</id>
+ <sha1>koevx105y5kuodft74oom7bfisa2w5r</sha1>
+ <revision>
+ <id>1055</id>
+ <timestamp>2014-01-31T07:39:55Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="1002">== Synopsis ==
+A regression test for category, sub-category and category hierarchies. A category hierarchy is specified as a collection of subordinate categories into a superordinate category. [https://semantic-mediawiki.org/wiki/Help:Special_property_Subcategory_of Subcategory of] classifies subordinate categories.
+
+== Usage ==
+[[:Category:Regression test]], [[:Category:Regression test category]], [[:Category:Regression test sub category]], [[:Category:Regression test sub sub category]]
+
+== Queries ==
+=== Search for specific a specific category ===
+{{#ask: [[Category:Regression test category]]
+ |?Category
+ |format=broadtable
+}}
+
+=== Wildcard search on 'Subcategory of' ===
+{{#ask: [[Subcategory of::+]]
+ |?Subcategory of
+ |format=broadtable
+}}
+
+=== Search for specific 'Subcategory of' ===
+{{#ask: [[Subcategory of::Regression test sub category]]
+ |?Subcategory of
+ |format=broadtable
+}}
+
+[[Category:Regression test]] [[Category:Regression test category]] [[Category:Category regression test]]</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/GenericLoremIpsumTest-Mw-1-19-7.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/GenericLoremIpsumTest-Mw-1-19-7.xml
new file mode 100644
index 00000000..1cd60afe
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/GenericLoremIpsumTest-Mw-1-19-7.xml
@@ -0,0 +1,270 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Property:Has annotation uri</title>
+ <ns>102</ns>
+ <id>503</id>
+ <sha1>ifvt9xhpsfkv04ehcnhpw3i88s0fsb8</sha1>
+ <revision>
+ <id>1342</id>
+ <timestamp>2014-03-29T16:51:25Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="53">[[Has type::Annotation URI]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has boolean</title>
+ <ns>102</ns>
+ <id>502</id>
+ <sha1>l3b3eelfib1em61uurletnc4kb1xlzh</sha1>
+ <revision>
+ <id>1338</id>
+ <timestamp>2014-03-29T16:47:13Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Boolean]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="46">[[Has type::Boolean]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has date</title>
+ <ns>102</ns>
+ <id>14</id>
+ <sha1>473nf5knraq99k8zsrg6z7o3812tu61</sha1>
+ <revision>
+ <id>1330</id>
+ <timestamp>2014-03-29T16:38:59Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Date]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has email</title>
+ <ns>102</ns>
+ <id>500</id>
+ <sha1>9puenjhr9dntyg9obgtwhvaenn98rav</sha1>
+ <revision>
+ <id>1334</id>
+ <timestamp>2014-03-29T16:42:38Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Email]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="44">[[Has type::Email]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has number</title>
+ <ns>102</ns>
+ <id>494</id>
+ <sha1>9fqf0pft61g8qqb8qtz1i5ayr1rmu30</sha1>
+ <revision>
+ <id>1321</id>
+ <timestamp>2014-03-29T16:30:26Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Number]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="45">[[Has type::Number]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has page</title>
+ <ns>102</ns>
+ <id>489</id>
+ <sha1>4sq0eljhm3yty9cifkvel3mv646ag0y</sha1>
+ <revision>
+ <id>1319</id>
+ <timestamp>2014-03-29T16:29:46Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Page]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has quantity</title>
+ <ns>102</ns>
+ <id>495</id>
+ <sha1>1ulyevjgdofvfrp7b6b17n7p0p6oy4w</sha1>
+ <revision>
+ <id>1323</id>
+ <timestamp>2014-03-29T16:34:24Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="219">[[Has type::Quantity]] [[Category:Lorem ipsum]]
+
+* [[Corresponds to::1 km²]]
+* [[Corresponds to::0.38610 sq mi]]
+* [[Corresponds to::1000 m²]]
+* [[Corresponds to::247.1054 acre]]
+* [[Corresponds to::988.4215 rood]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has temperature</title>
+ <ns>102</ns>
+ <id>501</id>
+ <sha1>925639l5wc4pwdmufjgza10rstpb2oa</sha1>
+ <revision>
+ <id>1336</id>
+ <timestamp>2014-03-29T16:45:35Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Temperature]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="50">[[Has type::Temperature]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has text</title>
+ <ns>102</ns>
+ <id>491</id>
+ <sha1>qi7oxp4101tdesdm3vavpgpfn1qe68u</sha1>
+ <revision>
+ <id>1320</id>
+ <timestamp>2014-03-29T16:30:07Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="43">[[Has type::Text]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has Url</title>
+ <ns>102</ns>
+ <id>499</id>
+ <sha1>1fw7q2wts7v11q1z6d31g89zorhco0i</sha1>
+ <revision>
+ <id>1332</id>
+ <timestamp>2014-03-29T16:40:28Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::URL]] [[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="42">[[Has type::URL]] [[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Lorem ipsum</title>
+ <ns>0</ns>
+ <id>493</id>
+ <sha1>94lztkh4kgb0mvjr87iyjfq4iv7ltlh</sha1>
+ <revision>
+ <id>1358</id>
+ <timestamp>2014-04-04T22:55:04Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="979">[[Has text::Lorem ipsum dolor sit amet consectetuer Maecenas adipiscing Pellentesque id sem]]. [[Has page::Elit Aliquam urna interdum]] morbi faucibus id tellus ipsum semper wisi. [[Has page::Platea enim hendrerit]] pellentesque consectetuer scelerisque Sed est felis felis quis. Auctor Proin In dolor id et ipsum vel at vitae ut. Praesent elit convallis Praesent aliquet pellentesque vel dolor pellentesque lacinia vitae. At tortor lacus Sed In interdum pulvinar et.
+
+[[Has number::1001]] [[Has quantity::10.25 km²]] [[Has date::1 Jan 2014]] [[Has Url::http://loremipsum.org/]] [[Has annotation uri::http://loremipsum.org/foaf.rdf]] [[Has email::Lorem@ipsum.org]] [[Has temperature::100 °C]] [[Has boolean::true]]
+
+{{#subobject:|Has number=1111|Has quantity=25 sqmi|Has date=January 4, 2010 7:00 pm|Has Url=http://example.org/some/|Has annotation uri=http://example.org/foaf.rdf|Has email=Lorem@example.org|Has temperature=100 °F|Has boolean=false}}
+
+[[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Platea enim hendrerit</title>
+ <ns>0</ns>
+ <id>498</id>
+ <sha1>4vp3ppszu168lv9f0tc9eaefvgbkv8a</sha1>
+ <revision>
+ <id>1327</id>
+ <timestamp>2014-03-29T16:36:22Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Category:Lorem ipsum]]&quot;</comment>
+ <text xml:space="preserve" bytes="24">[[Category:Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Elit Aliquam urna interdum</title>
+ <ns>0</ns>
+ <id>497</id>
+ <sha1>c5qjdsfni2zwsd95h59jiksolm1vjiv</sha1>
+ <revision>
+ <id>1361</id>
+ <timestamp>2014-04-04T23:00:14Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="945">[[Lorem ipsum]] dolor sit amet consectetuer Maecenas adipiscing Pellentesque id sem. [[Has text::Elit Aliquam urna interdum]] morbi faucibus id tellus ipsum semper wisi. [[Has page::Platea enim hendrerit]] pellentesque consectetuer scelerisque Sed est felis felis quis. Auctor Proin In dolor id et ipsum vel at vitae ut. Praesent elit convallis Praesent aliquet pellentesque vel dolor pellentesque lacinia vitae. At tortor lacus Sed In interdum pulvinar et.
+
+[[Has number::1001]] [[Has quantity::10.25 km²]] [[Has date::1 Jan 2014]] [[Has Url::http://loremipsum.org/]] [[Has annotation uri::http://loremipsum.org/foaf.rdf]] [[Has email::Lorem@ipsum.org]] [[Has temperature::100 °C]] [[Has boolean::true]]
+
+{{#set:|Has number=9999|Has quantity=0.25 m²|Has date=22 Jan 1714|Has Url=http://example.org/|Has annotation uri=http://example.org/foaf.rdf|Has email=Lorem@example.org|Has temperature=20 K|Has boolean=false}}
+
+[[Category: Lorem ipsum]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Lorem ipsum</title>
+ <ns>14</ns>
+ <id>496</id>
+ <sha1>sir97j6uzt9ev2uyhaz1aj4i3spogih</sha1>
+ <revision>
+ <id>1355</id>
+ <timestamp>2014-04-04T22:29:18Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="17">[[Category:Main]]</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/PageWithTemplateInclusionTest-Mw-1-19-7.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/PageWithTemplateInclusionTest-Mw-1-19-7.xml
new file mode 100644
index 00000000..2207b2d2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/PageWithTemplateInclusionTest-Mw-1-19-7.xml
@@ -0,0 +1,112 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/mw-19/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Foo-1-19-7</title>
+ <ns>0</ns>
+ <id>158</id>
+ <sha1>kyhp4t0b6nu2rvzftnzcxnbrxxwfa9d</sha1>
+ <revision>
+ <id>399</id>
+ <timestamp>2013-11-07T23:09:16Z</timestamp>
+ <contributor>
+ <ip>127.0.0.1</ip>
+ </contributor>
+ <text xml:space="preserve" bytes="267">[[Quux::garply]], {{#subobject:|Qeey=bam}}, {{#show: Foo-1-19-7|?Foo}}, {{#ask: [[Modification date::+]]|?Modification date}}
+
+{{FooTemplate|Foo=bar}}, {{FooSubobject|Qeey=bam}}, {{FooShow|Page=Foo-1-19-7}}, {{FooAsk|Query=[[Modification date::+]]}}
+
+[[Category:Regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Template:FooAsk</title>
+ <ns>10</ns>
+ <id>163</id>
+ <sha1>rxf4lv2hmwxsgr5n4wk6oiqcpgk5gcq</sha1>
+ <revision>
+ <id>394</id>
+ <timestamp>2013-11-07T19:39:59Z</timestamp>
+ <contributor>
+ <ip>127.0.0.1</ip>
+ </contributor>
+ <comment>Created page with &quot;{{#ask: {{{Query}}} |?Modification date}}&quot;</comment>
+ <text xml:space="preserve" bytes="41">{{#ask: {{{Query}}} |?Modification date}}</text>
+ </revision>
+ </page>
+ <page>
+ <title>Template:FooShow</title>
+ <ns>10</ns>
+ <id>162</id>
+ <sha1>lmye013mwzch8f6pzb1zpirqmaju4y4</sha1>
+ <revision>
+ <id>393</id>
+ <timestamp>2013-11-07T19:38:58Z</timestamp>
+ <contributor>
+ <ip>127.0.0.1</ip>
+ </contributor>
+ <comment>Created page with &quot;{{#show: {{{Page}}} |?Foo}}&quot;</comment>
+ <text xml:space="preserve" bytes="27">{{#show: {{{Page}}} |?Foo}}</text>
+ </revision>
+ </page>
+ <page>
+ <title>Template:FooSubobject</title>
+ <ns>10</ns>
+ <id>161</id>
+ <sha1>0ae8yc3i99f9n266mhtwnt63unxvsa5</sha1>
+ <revision>
+ <id>392</id>
+ <timestamp>2013-11-07T19:37:53Z</timestamp>
+ <contributor>
+ <ip>127.0.0.1</ip>
+ </contributor>
+ <comment>Created page with &quot;{{#subobject:|Qeey={{{Qeey}}} }}&quot;</comment>
+ <text xml:space="preserve" bytes="32">{{#subobject:|Qeey={{{Qeey}}} }}</text>
+ </revision>
+ </page>
+ <page>
+ <title>Template:FooTemplate</title>
+ <ns>10</ns>
+ <id>160</id>
+ <sha1>c2jf6txk9oex7bcfoggqg31n7fm9kxn</sha1>
+ <revision>
+ <id>391</id>
+ <timestamp>2013-11-07T19:34:39Z</timestamp>
+ <contributor>
+ <ip>127.0.0.1</ip>
+ </contributor>
+ <comment>Created page with &quot;[[Foo::{{{Foo}}}]]&quot;</comment>
+ <text xml:space="preserve" bytes="18">[[Foo::{{{Foo}}}]]</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RecordDataTypeTest-Mw-1-19-7.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RecordDataTypeTest-Mw-1-19-7.xml
new file mode 100644
index 00000000..34efd7e7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RecordDataTypeTest-Mw-1-19-7.xml
@@ -0,0 +1,279 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Category:Regression test</title>
+ <ns>14</ns>
+ <id>420</id>
+ <sha1>4s17yzvoj5kq6dzdmgnw7t1ukpr4tkz</sha1>
+ <revision>
+ <id>1035</id>
+ <timestamp>2014-01-31T07:30:44Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <minor/>
+ <comment>1 revision</comment>
+ <text xml:space="preserve" bytes="24">Regression test category</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Record type regression test</title>
+ <ns>14</ns>
+ <id>429</id>
+ <sha1>iegvvlibf0prco1vgdvofg9se788l1c</sha1>
+ <revision>
+ <id>1016</id>
+ <timestamp>2014-01-30T08:43:10Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;..&quot;</comment>
+ <text xml:space="preserve" bytes="2">..</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has record number field</title>
+ <ns>102</ns>
+ <id>426</id>
+ <sha1>r586wcwca63cjsed7r02w5qwgav0ewt</sha1>
+ <revision>
+ <id>1020</id>
+ <timestamp>2014-01-30T08:47:44Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="61">[[Has type::Number]] [[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has record page field</title>
+ <ns>102</ns>
+ <id>422</id>
+ <sha1>ioqobky2da020lawbedjfj0oh97llmj</sha1>
+ <revision>
+ <id>1021</id>
+ <timestamp>2014-01-30T08:48:02Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="59">[[Has type::Page]] [[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has record text field</title>
+ <ns>102</ns>
+ <id>423</id>
+ <sha1>ibdxt3wbzj6g3d5mx3c3khfa8nudyha</sha1>
+ <revision>
+ <id>1022</id>
+ <timestamp>2014-01-30T08:48:11Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="59">[[Has type::Text]] [[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has record type</title>
+ <ns>102</ns>
+ <id>425</id>
+ <sha1>2r74yeu1070rnprktpe8gnq4ocur15f</sha1>
+ <revision>
+ <id>1023</id>
+ <timestamp>2014-01-30T08:48:23Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="145">[[Has type::Record]] [[Has fields::Has record page field;Has record text field;Has record number field]] [[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has record type for single test</title>
+ <ns>102</ns>
+ <id>430</id>
+ <sha1>2r74yeu1070rnprktpe8gnq4ocur15f</sha1>
+ <revision>
+ <id>1027</id>
+ <timestamp>2014-01-30T09:36:54Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Record]] [[Has fields::Has record page field;Has record text field;Has record number field]] [[Category:Record type regression test]]&quot;</comment>
+ <text xml:space="preserve" bytes="145">[[Has type::Record]] [[Has fields::Has record page field;Has record text field;Has record number field]] [[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>RecordDataTypePage</title>
+ <ns>0</ns>
+ <id>428</id>
+ <sha1>anal6w4vsow54hlzfut4s13c93jdtkl</sha1>
+ <revision>
+ <id>1015</id>
+ <timestamp>2014-01-30T08:42:57Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>/* Usage */</comment>
+ <text xml:space="preserve" bytes="491">== Usage ==
+=== In-text annotation ===
+[[Has record type::FooPage;FooText;9001]], [[Has record type::QyuPage;?;9001]]
+
+=== Silent annotation using #set ===
+{{#set:
+ |Has record type=RecordDataTypePage;BarText;1009
+}}
+{{#set:
+ |Has record type=BooPage;?;1009
+}}
+
+=== Silent annotation using #subobject ===
+{{#subobject:
+ |Has record type=QyuPageOnSubobject;?;9999
+}}
+{{#subobject:
+ |Has record type=XeuiPageOnSubobject;XeuiTextOnSubobject;1111
+}}
+
+[[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>RecordDataTypeRegressionTest/WithSubpage</title>
+ <ns>0</ns>
+ <id>427</id>
+ <sha1>anal6w4vsow54hlzfut4s13c93jdtkl</sha1>
+ <revision>
+ <id>1017</id>
+ <timestamp>2014-01-30T08:43:30Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="491">== Usage ==
+=== In-text annotation ===
+[[Has record type::FooPage;FooText;9001]], [[Has record type::QyuPage;?;9001]]
+
+=== Silent annotation using #set ===
+{{#set:
+ |Has record type=RecordDataTypePage;BarText;1009
+}}
+{{#set:
+ |Has record type=BooPage;?;1009
+}}
+
+=== Silent annotation using #subobject ===
+{{#subobject:
+ |Has record type=QyuPageOnSubobject;?;9999
+}}
+{{#subobject:
+ |Has record type=XeuiPageOnSubobject;XeuiTextOnSubobject;1111
+}}
+
+[[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>RecordDataTypeRegressionTest</title>
+ <ns>0</ns>
+ <id>421</id>
+ <sha1>2ugdgp4h7m7pl11hzr02ba008voodsx</sha1>
+ <revision>
+ <id>1029</id>
+ <timestamp>2014-01-30T12:20:54Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="1704">== Synopsis ==
+A regression test for the record type. Semantic MediaWiki provides a record type representing other property values that consist of a short list of values of other datatypes. For more information about this data type, see [https://semantic-mediawiki.org/wiki/Help:Type_Record Help:Type Record].
+
+[[Property:Has record type]], [[Property:Has record page field]], [[Property:Has record text field]], [[Property:Has record number field]]
+
+[[RecordDataTypeRegressionTest/WithSubpage]], [[RecordDataTypePage]]
+
+== Usage ==
+=== In-text annotation ===
+[[Has record type for single test::ForSingleTestAsPage;ForSingleTestAsText;3333]] [[Has record type::FooPage;FooText;9001]], [[Has record type::QyuPage;?;9001]]
+
+=== Silent annotation using #set ===
+{{#set:
+ |Has record type=RecordDataTypePage;BarText;1009
+}}
+{{#set:
+ |Has record type=BooPage;?;1009
+}}
+
+=== Silent annotation using #subobject ===
+{{#subobject:
+ |Has record type=QyuPageOnSubobject;?;9999
+}}
+{{#subobject:
+ |Has record type=XeuiPageOnSubobject;XeuiTextOnSubobject;1111
+}}
+
+== Queries ==
+=== Simple query to search for specific value ===
+{{#ask: [[Has record page field::QyuPage]] OR [[Has record page field::QyuPageOnSubobject]]
+ |?#=Internal record page (as subobject)
+ |format=broadtable
+}}
+
+=== Wildcard search with compound listing ===
+{{#ask: [[Has record type::+]]
+ |?Has record type
+ |format=broadtable
+}}
+
+=== Wildcard search with individual field listing ===
+{{#ask: [[Has record page field::+]]
+ |?Has record page field
+ |?Has record text field
+ |?Has record number field
+ |format=broadtable
+}}
+
+[[Category:Regression test]] [[Category:Data type regression test]] [[Category:Record type regression test]]</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RedirectPageTest-Mw-1-19-7.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RedirectPageTest-Mw-1-19-7.xml
new file mode 100644
index 00000000..ba0293e3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/RedirectPageTest-Mw-1-19-7.xml
@@ -0,0 +1,113 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Category:Regression test</title>
+ <ns>14</ns>
+ <id>420</id>
+ <sha1>4s17yzvoj5kq6dzdmgnw7t1ukpr4tkz</sha1>
+ <revision>
+ <id>1035</id>
+ <timestamp>2014-01-31T07:30:44Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <minor/>
+ <comment>1 revision</comment>
+ <text xml:space="preserve" bytes="24">Regression test category</text>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Simple redirect test</title>
+ <ns>14</ns>
+ <id>429</id>
+ <sha1>iegvvlibf0prco1vgdvofg9se788l1c</sha1>
+ <revision>
+ <id>1016</id>
+ <timestamp>2014-01-30T08:43:10Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;..&quot;</comment>
+ <text xml:space="preserve" bytes="2">..</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has regression test</title>
+ <ns>102</ns>
+ <id>487</id>
+ <sha1>byqsaznmj8muv1x9qm7hky0dlasesr9</sha1>
+ <revision>
+ <id>1308</id>
+ <timestamp>2014-03-19T20:18:21Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::Page]]&quot;</comment>
+ <text xml:space="preserve" bytes="18">[[Has type::Page]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>ToBeSimplePageRedirect</title>
+ <ns>0</ns>
+ <id>484</id>
+ <redirect title="SimplePageRedirectRegressionTest" />
+ <sha1>cbkrfrdppwskfozybbkna7avfn6fkz4</sha1>
+ <revision>
+ <id>1309</id>
+ <timestamp>2014-03-19T20:19:25Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ </contributor>
+ <text xml:space="preserve" bytes="80">#REDIRECT [[SimplePageRedirectRegressionTest]] [[Category:Simple redirect test]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>SimplePageRedirectRegressionTest</title>
+ <ns>0</ns>
+ <id>483</id>
+ <sha1>d4d7j2mio0bveyg8dqqmumbz5pcie9n</sha1>
+ <revision>
+ <id>1307</id>
+ <timestamp>2014-03-19T20:17:57Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ </contributor>
+ <text xml:space="preserve" bytes="184">This is part of the [[PageRedirectRegressionTest]] [[Category:Regression test]] [[Category:Redirect test]] [[Category:Simple redirect test]] {{#set:|Has regression test=Redirect test}}</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/TimeDataTypeTest-Mw-1-19-7.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/TimeDataTypeTest-Mw-1-19-7.xml
new file mode 100644
index 00000000..e2cb720f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/TimeDataTypeTest-Mw-1-19-7.xml
@@ -0,0 +1,159 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.6/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.6/ http://www.mediawiki.org/xml/export-0.6.xsd" version="0.6" xml:lang="en-gb">
+ <siteinfo>
+ <sitename>MW-19</sitename>
+ <base>http://localhost:8080/w/index.php/Main_Page</base>
+ <generator>MediaWiki 1.19.7</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">MW-19</namespace>
+ <namespace key="5" case="first-letter">MW-19 talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="104" case="first-letter">Type</namespace>
+ <namespace key="105" case="first-letter">Type talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ <namespace key="160" case="first-letter">Foo</namespace>
+ <namespace key="161" case="first-letter">Foo talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Property:Has calendar date</title>
+ <ns>102</ns>
+ <id>412</id>
+ <sha1>annvc3ivc6e8dmmd3ljtgkv150g9plg</sha1>
+ <revision>
+ <id>908</id>
+ <timestamp>2014-01-21T06:13:12Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::date]]&quot;</comment>
+ <text xml:space="preserve" bytes="18">[[Has type::date]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has query date</title>
+ <ns>102</ns>
+ <id>413</id>
+ <sha1>annvc3ivc6e8dmmd3ljtgkv150g9plg</sha1>
+ <revision>
+ <id>909</id>
+ <timestamp>2014-01-21T06:13:16Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;[[Has type::date]]&quot;</comment>
+ <text xml:space="preserve" bytes="18">[[Has type::date]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Has date</title>
+ <ns>102</ns>
+ <id>14</id>
+ <sha1>qry1h86awxxalbl5f7vuhstlf0l4mz1</sha1>
+ <revision>
+ <id>901</id>
+ <timestamp>2014-01-20T13:27:26Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <minor/>
+ <comment>1 revision</comment>
+ <text xml:space="preserve" bytes="18">[[has type::date]]</text>
+ </revision>
+ </page>
+ <page>
+ <title>TimeDataTypeRegressionTest</title>
+ <ns>0</ns>
+ <id>404</id>
+ <sha1>10ig4ph0ci93sq8o9l47yh5nt4j33fl</sha1>
+ <revision>
+ <id>910</id>
+ <timestamp>2014-01-21T06:13:59Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <text xml:space="preserve" bytes="2792">== Synopsis ==
+A regression test for date type properties. [http://www.semantic-mediawiki.org/wiki/Help:Type_Date Examples] of typical input dates in English language are:
+{| class=&quot;wikitable&quot;
+|-
+|'''annotation'''||'''result'''||'''remark'''
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Feb 11 2000 10:00:01]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Feb 11 2000 10:00:01]]||complete date with time
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Feb 11 2000]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Feb 11 2000]]||just date
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::2000]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::2000]]||year by itself
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Feb 11 2000 10:00:01 PM]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Feb 11 2000 10:00:01 PM]]||complete date with time, PM
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Feb 11 2000 22:00:01]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Feb 11 2000 22:00:01]]||complete date with 24h time
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::2000-02-11T22:00:01]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::2000-02-11T22:00:01]]||ISO-style date
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::2000-02-11T22:00:01+02:00]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::2000-02-11T22:00:01+02:00]]||ISO-style date with offset
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::2000 February 2]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::2000 February 2]]||varying order of inputs is supported
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::2-3-2000]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::2-3-2000]]||preferred interpretation, month or day, sometimes depends on language settings
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::2/3/2000]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::2/3/2000]]||various kinds of separators are recognized in all languages
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Jan 1 300 BC]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Jan 1 300 BC]]||dates BC/before common era are supported
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::14000000000 BC]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::14000000000 BC]]||estimated age of the universe
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Feb 11 2000 Jl]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Feb 11 2000 Jl]]||date of the Julian Calendar
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Feb 11 1492 Gr]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Feb 11 1492 Gr]]||date is treated as Gregorian
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::Feb 11 2000 10:00 GMT]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::Feb 11 2000 10:00 GMT]]||date with time zone shortcut
+|-
+|&lt;tt&gt;&lt;nowiki&gt;[[Has date::2000-02-22]]&lt;/nowiki&gt;&lt;/tt&gt;||[[Has date::2000-02-22]]||MySQL date format
+|}
+
+{{#set:
+ |Has query date=January 4, 2010 7:00 pm
+ |Has query date=June 8, 2011
+ |Has query date=01 Jan 1980
+ |Has query date=Feb 11 2000 10:00 GMT
+ |Has query date=2/3/2000
+}}
+
+{{#set:
+ |Has calendar date=Jan 1 300 BC
+ |Has calendar date=14000000000 BC
+ |Has calendar date=Feb 11 2000 Jl
+ |Has calendar date=Feb 11 1492 Gr
+}}
+
+== Query ==
+{{#ask: [[Has query date::+]]|?Has query date|?Has query date#ISO|?Has query date#GR}}
+
+{{#ask: [[Has date::+]][[Category:Regression test]]|?Has date|?Has date#ISO=as ISO|?Has date#GR=as GR|?Has date#JL=as JL}}
+
+[[Category:Regression test]]</text>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/cicero-de-finibus.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/cicero-de-finibus.xml
new file mode 100644
index 00000000..a06523f6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/cicero-de-finibus.xml
@@ -0,0 +1,69 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
+ <siteinfo>
+ <sitename>mw-test</sitename>
+ <dbname>mw-test</dbname>
+ <base>http://localhost:8080/mw-test/index.php/Main_Page</base>
+ <generator>MediaWiki 1.25.1</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">mw-test</namespace>
+ <namespace key="5" case="first-letter">mw-test talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>Property:Has text</title>
+ <ns>102</ns>
+ <id>21</id>
+ <revision>
+ <id>4694</id>
+ <parentid>4693</parentid>
+ <timestamp>2015-08-05T20:09:22Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="91">[[Has type::Text]] [[Has property description::To contain strings of arbitrary length.@en]]</text>
+ <sha1>izpf4um41xce5g993zndg9t34diz6ql</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>De Finibus Bonorum et Malorum</title>
+ <ns>0</ns>
+ <id>1298</id>
+ <revision>
+ <id>4692</id>
+ <timestamp>2015-08-05T20:06:47Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;Has text::Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et...&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="879">[[Has text::Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?]]</text>
+ <sha1>cbgy9a7vlvh30498ruk2boehmc74tz9</sha1>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/dwc-import-example.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/dwc-import-example.xml
new file mode 100644
index 00000000..e6443d49
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Fixtures/dwc-import-example.xml
@@ -0,0 +1,307 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
+ <siteinfo>
+ <sitename>mw-test</sitename>
+ <dbname>mw-test</dbname>
+ <base>http://localhost:8080/mw-test/index.php/Main_Page</base>
+ <generator>MediaWiki 1.25.1</generator>
+ <case>first-letter</case>
+ <namespaces>
+ <namespace key="-2" case="first-letter">Media</namespace>
+ <namespace key="-1" case="first-letter">Special</namespace>
+ <namespace key="0" case="first-letter" />
+ <namespace key="1" case="first-letter">Talk</namespace>
+ <namespace key="2" case="first-letter">User</namespace>
+ <namespace key="3" case="first-letter">User talk</namespace>
+ <namespace key="4" case="first-letter">mw-test</namespace>
+ <namespace key="5" case="first-letter">mw-test talk</namespace>
+ <namespace key="6" case="first-letter">File</namespace>
+ <namespace key="7" case="first-letter">File talk</namespace>
+ <namespace key="8" case="first-letter">MediaWiki</namespace>
+ <namespace key="9" case="first-letter">MediaWiki talk</namespace>
+ <namespace key="10" case="first-letter">Template</namespace>
+ <namespace key="11" case="first-letter">Template talk</namespace>
+ <namespace key="12" case="first-letter">Help</namespace>
+ <namespace key="13" case="first-letter">Help talk</namespace>
+ <namespace key="14" case="first-letter">Category</namespace>
+ <namespace key="15" case="first-letter">Category talk</namespace>
+ <namespace key="102" case="first-letter">Property</namespace>
+ <namespace key="103" case="first-letter">Property talk</namespace>
+ <namespace key="108" case="first-letter">Concept</namespace>
+ <namespace key="109" case="first-letter">Concept talk</namespace>
+ </namespaces>
+ </siteinfo>
+ <page>
+ <title>MediaWiki:Smw import dwc</title>
+ <ns>8</ns>
+ <id>1287</id>
+ <revision>
+ <id>4669</id>
+ <timestamp>2015-08-05T18:38:11Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;http://rs.tdwg.org/dwc/terms/|[http://rs.tdwg.org/dwc/terms/ Darwin Core Terms (DwC)] scientificName|Type:Text vernacularName|Type:Monolingual text taxonID|Type:Text kingd...&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="299">http://rs.tdwg.org/dwc/terms/|[http://rs.tdwg.org/dwc/terms/ Darwin Core Terms (DwC)]
+ scientificName|Type:Text
+ vernacularName|Type:Monolingual text
+ taxonID|Type:Text
+ kingdom|Type:Text
+ phylum|Type:Text
+ family|Type:Text
+ genus|Type:Text
+ order|Type:Text
+ class|Type:Text
+
+[[Category:Dwc import]]</text>
+ <sha1>14269h4v28zrlit9yhq25mj2nhzxomp</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Category:Dwc import</title>
+ <ns>14</ns>
+ <id>1291</id>
+ <revision>
+ <id>4673</id>
+ <timestamp>2015-08-05T18:39:29Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;http://rs.tdwg.org/dwc/terms/&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="29">http://rs.tdwg.org/dwc/terms/</text>
+ <sha1>gaz4e878f2b2sie5mo6b7aeyndbq0d4</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:genus</title>
+ <ns>102</ns>
+ <id>1290</id>
+ <revision>
+ <id>4672</id>
+ <timestamp>2015-08-05T18:39:08Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;* [[Imported from::dwc:genus]] {{DISPLAYTITLE:dwc:genus}} [[Category:Dwc import]]&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="82">* [[Imported from::dwc:genus]] {{DISPLAYTITLE:dwc:genus}}
+
+[[Category:Dwc import]]</text>
+ <sha1>gsxqimgmffeoojuc7mtdx7xjyzgrdua</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:kingdom</title>
+ <ns>102</ns>
+ <id>1292</id>
+ <revision>
+ <id>4676</id>
+ <parentid>4675</parentid>
+ <timestamp>2015-08-05T18:41:15Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="775">* [[Imported from::dwc:kingdom]] {{DISPLAYTITLE:dwc:kingdom}}
+* Property description:
+** [[Has property description::The full scientific name of the kingdom in which the taxon is classified. (&quot;Animalia&quot;, &quot;Plantae&quot;)@en]]
+** [[Has property description::El nombre científico completo del reino en el que se clasifica el taxón.@es]]
+** [[Has property description::分类å•å…ƒæ‰€å±žç•Œçš„完整学å。@zh-Hans]]
+** [[Has property description::ãã®åˆ†é¡žç¾¤ãŒä½ç½®ã¥ã‘られã¦ã„ã‚‹ã€åˆ†é¡žä¸Šã®ã€Œç•Œã€ã®ãƒ•ãƒ«ãƒãƒ¼ãƒ ã€‚@ja]]
+** [[Has property description::Le nom scientifique complet du règne dans lequel le taxon est classé@fr]]
+
+Retrieved 20:32, February 29, 2016 from http://terms.tdwg.org/w/index.php?title=dwc:kingdom&amp;oldid=10142
+
+[[Category:Dwc import]]</text>
+ <sha1>jdgcwwgncncbui9un4h14p4zyqki1m3</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:order</title>
+ <ns>102</ns>
+ <id>1293</id>
+ <revision>
+ <id>4677</id>
+ <timestamp>2015-08-05T18:42:18Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;* [[Imported from::dwc:order]] {{DISPLAYTITLE:dwc:order}} [[Category:Dwc import]]&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="82">* [[Imported from::dwc:order]] {{DISPLAYTITLE:dwc:order}}
+
+[[Category:Dwc import]]</text>
+ <sha1>asv9cxea8cm6lr4luptlimsvau0oagz</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:phylum</title>
+ <ns>102</ns>
+ <id>1294</id>
+ <revision>
+ <id>4679</id>
+ <timestamp>2015-08-05T18:43:11Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;* [[Imported from::dwc:phylum]] {{DISPLAYTITLE:dwc:phylum}} [[Category:Dwc import]]&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="84">* [[Imported from::dwc:phylum]] {{DISPLAYTITLE:dwc:phylum}}
+
+[[Category:Dwc import]]</text>
+ <sha1>i9rkmrniujg125dykx2ka2fkdv85kdc</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:scientificName</title>
+ <ns>102</ns>
+ <id>1295</id>
+ <revision>
+ <id>4680</id>
+ <timestamp>2015-08-05T18:43:47Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;* [[Imported from::dwc:scientificName]] {{DISPLAYTITLE:dwc:scientificName}} [[Category:Dwc import]]&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="100">* [[Imported from::dwc:scientificName]] {{DISPLAYTITLE:dwc:scientificName}}
+
+[[Category:Dwc import]]</text>
+ <sha1>4r77lhnl3jsbazjgxqrr3i4qdvm5bil</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:taxonID</title>
+ <ns>102</ns>
+ <id>1296</id>
+ <revision>
+ <id>4681</id>
+ <timestamp>2015-08-05T18:45:07Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <comment>Created page with &quot;* [[Imported from::dwc:taxonID]] {{DISPLAYTITLE:dwc:taxonID}} [[Category:Dwc import]]&quot;</comment>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="86">* [[Imported from::dwc:taxonID]] {{DISPLAYTITLE:dwc:taxonID}}
+
+[[Category:Dwc import]]</text>
+ <sha1>gzoh496mp6y6xzeihd08xitzd6fo18c</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:vernacularName</title>
+ <ns>102</ns>
+ <id>1297</id>
+ <revision>
+ <id>4689</id>
+ <parentid>4688</parentid>
+ <timestamp>2015-08-05T18:54:18Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="663">* [[Imported from::dwc:vernacularName]] {{DISPLAYTITLE:dwc:vernacularName}}
+* Property description:
+** [[Has property description::A common or vernacular name@en]]
+** [[Has property description::Nom commun ou vernaculaire@fr]]
+** [[Has property description::Ein geräuchlicher Name oder Volksname@de]]
+** [[Has property description::Ein geräuchlicher Name oder Volksname@de]]
+** [[Has property description::一般åã€ã‚ã‚‹ã„ã¯é€šä¿—å@ja]]
+** [[Has property description::一个常è§æˆ–者俗å@zh-Hans]]
+** [[Has property description::Un nombre común o vernacular@es]]
+
+http://terms.tdwg.org/w/index.php?title=dwc:vernacularName
+
+[[Category:Dwc import]]</text>
+ <sha1>pdeh0ku8smvn732nlxvshf82km6j9km</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:class</title>
+ <ns>102</ns>
+ <id>1288</id>
+ <revision>
+ <id>4683</id>
+ <parentid>4670</parentid>
+ <timestamp>2015-08-05T18:46:00Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="82">* [[Imported from::dwc:class]] {{DISPLAYTITLE:dwc:class}}
+
+[[Category:Dwc import]]</text>
+ <sha1>mlkipjysemqufxpfqd96qro2pvrbdmq</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>Property:Dwc:family</title>
+ <ns>102</ns>
+ <id>1289</id>
+ <revision>
+ <id>4684</id>
+ <parentid>4671</parentid>
+ <timestamp>2015-08-05T18:46:11Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="84">* [[Imported from::dwc:family]] {{DISPLAYTITLE:dwc:family}}
+
+[[Category:Dwc import]]</text>
+ <sha1>ed6vrz42groes5xa8jhrrsbfdrdifmg</sha1>
+ </revision>
+ </page>
+ <page>
+ <title>GBIFID:2706490</title>
+ <ns>0</ns>
+ <id>1286</id>
+ <revision>
+ <id>4691</id>
+ <parentid>4690</parentid>
+ <timestamp>2015-08-05T18:55:46Z</timestamp>
+ <contributor>
+ <username>Tester</username>
+ <id>1</id>
+ </contributor>
+ <model>wikitext</model>
+ <format>text/x-wiki</format>
+ <text xml:space="preserve" bytes="497">[[dwc:scientificName::Agrostis capillaris L.]]
+
+* [[dwc:kingdom::Plantea]]
+* [[dwc:phylum::Magnoliophyta]]
+* [[dwc:class::Liliopsida]]
+* [[dwc:order::Poales]]
+* [[dwc:family::Poaceae]]
+* [[dwc:genus::Agrostis]]
+* [[dwc:vernacularName::Gewoon struisgras@en]] [[dwc:vernacularName::Rotes Straußgras@de]] [[dwc:vernacularName::Agrostis commun@fr]] [[dwc:vernacularName::Agrostis capillaris@es]]
+* [[dwc:taxonID::1365]]
+
+[[Category:Dwc import]] __SHOWFACTBOX__ {{DISPLAYTITLE:Agrostis capillaris L.}}</text>
+ <sha1>77qals7ynkvp7t6spigid49yy59gkje</sha1>
+ </revision>
+ </page>
+</mediawiki>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/DumpRdfMaintenanceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/DumpRdfMaintenanceTest.php
new file mode 100644
index 00000000..a0b71d30
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/DumpRdfMaintenanceTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import\Maintenance;
+
+use SMW\ApplicationFactory;
+use SMW\EventHandler;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class DumpRdfMaintenanceTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( "Skipping this test, MW 1.19 doesn't clean-up the title cache correctly." );
+ }
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+
+ ApplicationFactory::getInstance()->getSettings()->set( 'smwgExportBCAuxiliaryUse', true );
+ EventHandler::getInstance()->getEventDispatcher()->dispatch( 'exporter.reset' );
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/../Fixtures/' . 'GenericLoremIpsumTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+ ApplicationFactory::getInstance()->clear();
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testMaintenanceRdfOutput() {
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->importedTitles = [
+ 'Category:Lorem ipsum',
+ 'Lorem ipsum',
+ 'Elit Aliquam urna interdum',
+ 'Platea enim hendrerit',
+ 'Property:Has Url',
+ 'Property:Has annotation uri',
+ 'Property:Has boolean',
+ 'Property:Has date',
+ 'Property:Has email',
+ 'Property:Has number',
+ 'Property:Has page',
+ 'Property:Has quantity',
+ 'Property:Has temperature',
+ 'Property:Has text'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\DumpRdf' );
+ $maintenanceRunner->setQuiet();
+
+ $this->doExportForDefaultOptions( $maintenanceRunner );
+ $this->doExportForPageOption( $maintenanceRunner );
+ }
+
+ private function doExportForDefaultOptions( $maintenanceRunner ) {
+
+ $expectedOutputContent = [
+ // '<rdf:type rdf:resource="&wiki;Category-3ALorem_ipsum"/>',
+ '<rdfs:label>Lorem ipsum</rdfs:label>',
+ '<rdfs:label>Has annotation uri</rdfs:label>',
+ '<rdfs:label>Has boolean</rdfs:label>',
+ '<rdfs:label>Has date</rdfs:label>',
+ '<rdfs:label>Has email</rdfs:label>',
+ '<rdfs:label>Has number</rdfs:label>',
+ '<rdfs:label>Has page</rdfs:label>',
+ '<rdfs:label>Has quantity</rdfs:label>',
+ '<rdfs:label>Has temperature</rdfs:label>',
+ '<rdfs:label>Has text</rdfs:label>',
+ '<rdfs:label>Has Url</rdfs:label>',
+ ];
+
+ $maintenanceRunner->run();
+
+ $this->stringValidator->assertThatStringContains(
+ $expectedOutputContent,
+ $maintenanceRunner->getOutput()
+ );
+ }
+
+ private function doExportForPageOption( $maintenanceRunner ) {
+
+ $expectedOutputContent = [
+ '<rdfs:label>Lorem ipsum</rdfs:label>',
+ '<swivt:masterPage rdf:resource="&wiki;Lorem_ipsum"/>',
+ '<property:Has_subobject-23aux rdf:resource="&wiki;Lorem_ipsum-23_b704f46f7acbb89982564cc97d8e9019"/>',
+ '<swivt:wikiPageSortKey rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Lorem ipsum</swivt:wikiPageSortKey>'
+ ];
+
+ $maintenanceRunner
+ ->setOptions( [ 'page' => 'Lorem ipsum' ] )
+ ->run();
+
+ $this->stringValidator->assertThatStringContains(
+ $expectedOutputContent,
+ $maintenanceRunner->getOutput()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildConceptCacheMaintenanceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildConceptCacheMaintenanceTest.php
new file mode 100644
index 00000000..38235df1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildConceptCacheMaintenanceTest.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import\Maintenance;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class RebuildConceptCacheMaintenanceTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+ $this->pageCreator = UtilityFactory::getInstance()->newPageCreator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/../Fixtures/' . 'GenericLoremIpsumTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testRebuildConceptCache() {
+
+ $this->importedTitles = [
+ 'Category:Lorem ipsum',
+ 'Lorem ipsum',
+ 'Elit Aliquam urna interdum',
+ 'Platea enim hendrerit',
+ 'Property:Has Url',
+ 'Property:Has annotation uri',
+ 'Property:Has boolean',
+ 'Property:Has date',
+ 'Property:Has email',
+ 'Property:Has number',
+ 'Property:Has page',
+ 'Property:Has quantity',
+ 'Property:Has temperature',
+ 'Property:Has text'
+ ];
+
+ // 1.19 Title/LinkCache goes nuts for when a page in a previous test got
+ // deleted
+ // $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $conceptPage = $this->createConceptPage( 'Lorem ipsum concept', '[[Category:Lorem ipsum]]' );
+ $this->importedTitles[] = $conceptPage;
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\RebuildConceptCache' );
+ $maintenanceRunner->setQuiet();
+
+ $maintenanceRunner
+ ->setOptions( [ 'status' => true ] )
+ ->run();
+
+ $this->assertInstanceOf(
+ 'SMW\DIConcept',
+ $this->getStore()->getConceptCacheStatus( $conceptPage->getTitle() )
+ );
+
+ $maintenanceRunner
+ ->setOptions( [ 'create' => true ] )
+ ->run();
+
+ $maintenanceRunner
+ ->setOptions( [ 'delete' => true ] )
+ ->run();
+
+ $maintenanceRunner
+ ->setOptions( [ 'create' => true, 's' => 1 ] )
+ ->run();
+
+ $maintenanceRunner
+ ->setOptions( [ 'create' => true, 's' => 1, 'e' => 100 ] )
+ ->run();
+
+ $maintenanceRunner
+ ->setOptions( [ 'create' => true, 'update' => true, 'old' => 1 ] )
+ ->run();
+
+ $maintenanceRunner
+ ->setOptions( [ 'delete' => true, 'concept' => 'Lorem ipsum concept' ] )
+ ->run();
+ }
+
+ protected function createConceptPage( $name, $condition ) {
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( $name, SMW_NS_CONCEPT ) )
+ ->doEdit( "{{#concept: {$condition} }}" );
+
+ return $this->pageCreator->getPage();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildDataMaintenanceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildDataMaintenanceTest.php
new file mode 100644
index 00000000..3e521e7c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildDataMaintenanceTest.php
@@ -0,0 +1,175 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import\Maintenance;
+
+use SMW\DIProperty;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\ByPageSemanticDataFinder;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class RebuildDataMaintenanceTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/../Fixtures/' . 'GenericLoremIpsumTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testRebuildData() {
+
+ $this->importedTitles = [
+ 'Category:Lorem ipsum',
+ 'Lorem ipsum',
+ 'Elit Aliquam urna interdum',
+ 'Platea enim hendrerit',
+ 'Property:Has Url',
+ 'Property:Has annotation uri',
+ 'Property:Has boolean',
+ 'Property:Has date',
+ 'Property:Has email',
+ 'Property:Has number',
+ 'Property:Has page',
+ 'Property:Has quantity',
+ 'Property:Has temperature',
+ 'Property:Has text'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $main = Title::newFromText( 'Lorem ipsum' );
+
+ $expectedSomeProperties = [
+ 'properties' => [
+ new DIProperty( 'Has boolean' ),
+ new DIProperty( 'Has date' ),
+ new DIProperty( 'Has email' ),
+ new DIProperty( 'Has number' ),
+ new DIProperty( 'Has page' ),
+ new DIProperty( 'Has quantity' ),
+ new DIProperty( 'Has temperature' ),
+ new DIProperty( 'Has text' ),
+ new DIProperty( 'Has Url' ),
+ new DIProperty( 'Has annotation uri' )
+ ]
+ ];
+
+ $this->maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\RebuildData' );
+ $this->maintenanceRunner->setQuiet();
+
+ $this->semanticDataFinder = new ByPageSemanticDataFinder;
+ $this->semanticDataFinder->setTitle( $main )->setStore( $this->getStore() );
+
+ $this->assertRunWithoutOptions( $expectedSomeProperties );
+ $this->assertRunWithFullDeleteOption( $expectedSomeProperties );
+ $this->assertRunWithIdRangeOption( $expectedSomeProperties );
+ $this->assertRunWithCategoryOption( $expectedSomeProperties );
+ $this->assertRunWithSparqlStoreForPropertyOption( $expectedSomeProperties );
+ $this->assertRunWithSparqlStoreForQueryOption( $expectedSomeProperties );
+ }
+
+ protected function assertRunWithoutOptions( $expectedSomeProperties ) {
+ $this->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $this->maintenanceRunner->run()
+ );
+ }
+
+ protected function assertRunWithFullDeleteOption( $expectedSomeProperties ) {
+
+ $options = [
+ 'f' => true,
+ 'no-cache' => true,
+ 'debug' => true,
+ 'report-runtime' => true
+ ];
+
+ $this->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $this->maintenanceRunner->setOptions( $options )->run()
+ );
+ }
+
+ protected function assertRunWithIdRangeOption( $expectedSomeProperties ) {
+ $this->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $this->maintenanceRunner->setOptions( [ 's' => 1, 'e' => 10 ] )->run()
+ );
+ }
+
+ protected function assertRunWithCategoryOption( $expectedSomeProperties ) {
+ $this->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $this->maintenanceRunner->setOptions( [ 'c' => true ] )->run()
+ );
+ }
+
+ protected function assertRunWithSparqlStoreForPropertyOption( $expectedSomeProperties ) {
+ $this->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $this->maintenanceRunner->setOptions( [
+ 'p' => true,
+ 'b' => 'SMWSparqlStore' ] )->run()
+ );
+ }
+
+ protected function assertRunWithSparqlStoreForQueryOption( $expectedSomeProperties ) {
+ $this->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $this->maintenanceRunner->setOptions( [
+ 'query' => '[[Has Url::+]]',
+ 'b' => 'SMWSparqlStore' ] )->run()
+ );
+ }
+
+ private function assertThatPropertiesAreSet( $expectedSomeProperties, $runner ) {
+
+ $this->assertTrue( $runner );
+
+ $runPropertiesAreSetAssert = $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $this->semanticDataFinder->fetchFromStore()
+ );
+
+ $this->assertTrue( $runPropertiesAreSetAssert );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildFulltextSearchTableTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildFulltextSearchTableTest.php
new file mode 100644
index 00000000..e23cbd83
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildFulltextSearchTableTest.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import\Maintenance;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+
+/**
+ * @group semantic-mediawiki
+ * @group large
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class RebuildFulltextSearchTableTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = $this->testEnvironment->getUtilityFactory()->newRunnerFactory();
+ $this->titleValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newTitleValidator();
+
+ // Remove any predisposed settings
+ $this->testEnvironment->tearDown();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/../Fixtures/cicero-de-finibus.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->flushPages( $this->importedTitles );
+ parent::tearDown();
+ }
+
+ public function testCanRun() {
+
+ $this->importedTitles = [
+ 'De Finibus Bonorum et Malorum'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\RebuildFulltextSearchTable' );
+ $maintenanceRunner->setQuiet()->run();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildPropertyStatisticsMaintenanceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildPropertyStatisticsMaintenanceTest.php
new file mode 100644
index 00000000..3fed95e0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/RebuildPropertyStatisticsMaintenanceTest.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import\Maintenance;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class RebuildPropertyStatisticsMaintenanceTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/../Fixtures/' . 'GenericLoremIpsumTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testRebuildPropertyStatistics() {
+
+ $this->importedTitles = [
+ 'Category:Lorem ipsum',
+ 'Lorem ipsum',
+ 'Elit Aliquam urna interdum',
+ 'Platea enim hendrerit',
+ 'Property:Has Url',
+ 'Property:Has annotation uri',
+ 'Property:Has boolean',
+ 'Property:Has date',
+ 'Property:Has email',
+ 'Property:Has number',
+ 'Property:Has page',
+ 'Property:Has quantity',
+ 'Property:Has temperature',
+ 'Property:Has text'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\RebuildPropertyStatistics' );
+ $maintenanceRunner->setQuiet()->run();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/UpdateEntityCollationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/UpdateEntityCollationTest.php
new file mode 100644
index 00000000..b6cb2285
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/Maintenance/UpdateEntityCollationTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import\Maintenance;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class UpdateEntityCollationTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/../Fixtures/' . 'GenericLoremIpsumTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testSortFieldUpdate() {
+
+ $this->importedTitles = [
+ 'Category:Lorem ipsum',
+ 'Lorem ipsum',
+ 'Elit Aliquam urna interdum',
+ 'Platea enim hendrerit',
+ 'Property:Has Url',
+ 'Property:Has annotation uri',
+ 'Property:Has boolean',
+ 'Property:Has date',
+ 'Property:Has email',
+ 'Property:Has number',
+ 'Property:Has page',
+ 'Property:Has quantity',
+ 'Property:Has temperature',
+ 'Property:Has text'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $maintenanceRunner = $this->runnerFactory->newMaintenanceRunner( 'SMW\Maintenance\UpdateEntityCollation' );
+ $maintenanceRunner->setQuiet()->run();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/PageWithTemplateInclusionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/PageWithTemplateInclusionTest.php
new file mode 100644
index 00000000..c26ce126
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/PageWithTemplateInclusionTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import;
+
+use SMW\DIProperty;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\ByPageSemanticDataFinder;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class PageWithTemplateInclusionTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/'. 'Fixtures/' . 'PageWithTemplateInclusionTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testImportToVerifyAnnotationByTemplateInclusion() {
+
+ $this->importedTitles = [
+ 'Foo-1-19-7',
+ 'Template:FooAsk',
+ 'Template:FooShow',
+ 'Template:FooSubobject',
+ 'Template:FooTemplate'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $expectedProperties = [
+ 'properties' => [
+ DIProperty::newFromUserLabel( 'Foo' ),
+ DIProperty::newFromUserLabel( 'Quux' ),
+ new DIProperty( '_ASK' ),
+ new DIProperty( '_MDAT' ),
+ new DIProperty( '_SKEY' ),
+ new DIProperty( '_SOBJ' ),
+ new DIProperty( '_INST' )
+ ]
+ ];
+
+ $title = Title::newFromText( 'Foo-1-19-7' );
+
+ $semanticDataFinder = new ByPageSemanticDataFinder();
+ $semanticDataFinder
+ ->setTitle( $title )
+ ->setStore( $this->getStore() );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expectedProperties,
+ $semanticDataFinder->fetchFromOutput()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RecordDataTypeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RecordDataTypeTest.php
new file mode 100644
index 00000000..2ea25f90
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RecordDataTypeTest.php
@@ -0,0 +1,228 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\ByPageSemanticDataFinder;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group Database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class RecordDataTypeTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/'. 'Fixtures/' . 'RecordDataTypeTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testImportOfRecordValues() {
+
+ $this->importedTitles = [
+ 'Property:Has record number field',
+ 'Property:Has record page field',
+ 'Property:Has record text field',
+ 'Property:Has record type',
+ 'Property:Has record type for single test',
+ 'RecordDataTypePage',
+ 'RecordDataTypeRegressionTest/WithSubpage',
+ 'RecordDataTypeRegressionTest'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $title = Title::newFromText( 'RecordDataTypeRegressionTest' );
+
+ $expectedCategoryAsWikiValue = [
+ 'property' => new DIProperty( '_INST' ),
+ 'propertyValues' => [
+ 'Regression test',
+ 'Data type regression test',
+ 'Record type regression test'
+ ]
+ ];
+
+ $expectedSomeProperties = [
+ 'properties' => [
+ DIProperty::newFromUserLabel( 'RecordDataTypePage' ),
+ DIProperty::newFromUserLabel( 'BarText' ),
+ DIProperty::newFromUserLabel( 'BooPage' ),
+ DIProperty::newFromUserLabel( 'FooPage' ),
+ DIProperty::newFromUserLabel( 'QyuPage' ),
+ new DIProperty( '_ASK' ),
+ new DIProperty( '_MDAT' ),
+ new DIProperty( '_SKEY' ),
+ new DIProperty( '_SOBJ' ),
+ new DIProperty( '_INST' )
+ ]
+ ];
+
+ $property = DIProperty::newFromUserLabel( 'Has record type for single test' );
+ $valueString = 'ForSingleTestAsPage;ForSingleTestAsText;3333';
+
+ if ( $property->findPropertyTypeID() === '_rec' ) {
+ $valueString = 'ForSingleTestAsPage; ForSingleTestAsText; 3333';
+ }
+
+ $expectedRecordTypeValuesAsWikiValue = [
+ 'subject' => DIWikiPage::newFromTitle( $title ),
+ 'record' => $property,
+ 'property' => $property,
+ 'propertyValues' => [ $valueString, '?; ?; ?' ]
+ ];
+
+ $expectedRecordPageFieldValuesAsWikiValue = [
+ 'subject' => DIWikiPage::newFromTitle( $title ),
+ 'record' => DIProperty::newFromUserLabel( 'Has record type' ),
+ 'property' => DIProperty::newFromUserLabel( 'Has record page field' ),
+ 'propertyValues' => [
+ 'FooPage',
+ 'QyuPageOnSubobject',
+ 'QyuPage',
+ 'XeuiPageOnSubobject',
+ 'RecordDataTypePage',
+ 'BooPage'
+ ]
+ ];
+
+ $expectedRecordTextFieldValuesAsWikiValue = [
+ 'subject' => DIWikiPage::newFromTitle( $title ),
+ 'record' => DIProperty::newFromUserLabel( 'Has record type' ),
+ 'property' => DIProperty::newFromUserLabel( 'Has record text field' ),
+ 'propertyValues' => [
+ 'BarText',
+ 'ForSingleTestAsText',
+ 'FooText',
+ 'XeuiTextOnSubobject'
+ ]
+ ];
+
+ $expectedRecordNumberFieldValuesAsNumber = [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'RecordDataTypeRegressionTest/WithSubpage' ) ),
+ 'record' => DIProperty::newFromUserLabel( 'Has record type' ),
+ 'property' => DIProperty::newFromUserLabel( 'Has record number field' ),
+ 'propertyValues' => [
+ 1111,
+ 9001,
+ 9999,
+ 1009
+ ]
+ ];
+
+ $semanticDataFinder = new ByPageSemanticDataFinder;
+ $semanticDataFinder->setTitle( $title )->setStore( $this->getStore() );
+
+ $semanticDataBatches = [
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $title ) ),
+ ];
+
+ foreach ( $semanticDataBatches as $semanticData ) {
+
+ $this->semanticDataValidator->assertThatCategoriesAreSet(
+ $expectedCategoryAsWikiValue,
+ $semanticData
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $semanticData
+ );
+
+ $this->assertThatSemanticDataValuesAreSet( $expectedRecordTypeValuesAsWikiValue, $semanticData );
+ }
+
+ $this->assertThatRecordValuesAreSet( $expectedRecordTypeValuesAsWikiValue );
+ $this->assertThatRecordValuesAreSet( $expectedRecordPageFieldValuesAsWikiValue );
+ $this->assertThatRecordValuesAreSet( $expectedRecordTextFieldValuesAsWikiValue );
+ $this->assertThatRecordValuesAreSet( $expectedRecordNumberFieldValuesAsNumber );
+ }
+
+ protected function assertThatSemanticDataValuesAreSet( $expected, $semanticData ) {
+
+ $runValueAssert = false;
+
+ foreach ( $semanticData->getProperties() as $property ) {
+
+ if ( $property->equals( $expected['property'] ) ) {
+ $runValueAssert = true;
+ $this->semanticDataValidator->assertThatPropertyValuesAreSet(
+ $expected,
+ $property,
+ $semanticData->getPropertyValues( $property )
+ );
+ }
+
+ }
+
+ // Issue #124 needs to be resolved first
+ // $this->assertTrue( $runValueAssert, __METHOD__ );
+ }
+
+ protected function assertThatRecordValuesAreSet( $expected ) {
+
+ $runValueAssert = false;
+ $values = [];
+
+ $container = $this->getStore()->getPropertyValues(
+ $expected['subject'],
+ $expected['record']
+ );
+
+ foreach ( $container as $record ) {
+ $values = array_merge(
+ $values,
+ $this->getStore()->getPropertyValues( $record, $expected['property'] )
+ );
+ }
+
+ $this->semanticDataValidator->assertThatPropertyValuesAreSet(
+ $expected,
+ $expected['property'],
+ $values
+ );
+
+ // Issue #124 needs to be resolved first
+ // $this->assertTrue( $runValueAssert, __METHOD__ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RedirectPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RedirectPageTest.php
new file mode 100644
index 00000000..538cb70f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/RedirectPageTest.php
@@ -0,0 +1,215 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\InSemanticDataFetcher;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class RedirectPageTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $semanticDataValidator;
+ private $pageRefresher;
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->runnerFactory = $this->testEnvironment->getUtilityFactory()->newRunnerFactory();
+ $this->titleValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newTitleValidator();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+
+ $this->pageRefresher = $this->testEnvironment->getUtilityFactory()->newPageRefresher();
+ $this->pageCreator = $this->testEnvironment->getUtilityFactory()->newPageCreator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/'. 'Fixtures/' . 'RedirectPageTest-Mw-1-19-7.xml'
+ );
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->flushPages( $this->importedTitles );
+ parent::tearDown();
+ }
+
+ public function testPageImportToCreateRedirect() {
+
+ $this->importedTitles = [
+ 'SimplePageRedirectRegressionTest',
+ 'ToBeSimplePageRedirect'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $main = Title::newFromText( 'SimplePageRedirectRegressionTest' );
+
+ $expectedCategoryAsWikiValue = [
+ 'property' => new DIProperty( DIProperty::TYPE_CATEGORY ),
+ 'propertyValues' => [
+ 'Regression test',
+ 'Redirect test',
+ 'Simple redirect test'
+ ]
+ ];
+
+ $expectedSomeProperties = [
+ 'properties' => [
+ new DIProperty( 'Has regression test' )
+ ]
+ ];
+
+ $expectedRedirectAsWikiValue = [
+ 'property' => new DIProperty( '_REDI' ),
+ 'propertyValues' => [
+ 'ToBeSimplePageRedirect',
+ 'NewPageRedirectRegressionTest',
+ 'NewTargetPageRedirectRegressionTest'
+ ]
+ ];
+
+ $newRedirectPage = $this->createPageWithRedirectFor(
+ 'NewPageRedirectRegressionTest',
+ 'SimplePageRedirectRegressionTest'
+ );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->movePageToTargetRedirect(
+ $newRedirectPage,
+ 'NewTargetPageRedirectRegressionTest'
+ );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->pageRefresher->doRefreshPoolOfPages( [
+ $main,
+ $newRedirectPage,
+ 'NewTargetPageRedirectRegressionTest'
+ ] );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $semanticDataBatches = [
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $main ) ),
+ ];
+
+ // Something changed in MW since 1.28 that causes a
+ // "SMW\Tests\Utils\Validators\SemanticDataValidator::assertContainsPropertyValues
+ // for '_INST' as '__sin' with (Regression test, Redirect test, Simple redirect test)
+ // Failed asserting that an array contains 'Lorem ipsum'." and since I'm not sure
+ // about the cause, this part is disabled and awaits an investigation
+
+ // $this->assertThatCategoriesAreSet(
+ // $expectedCategoryAsWikiValue,
+ // $semanticDataBatches
+ // );
+
+ $this->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $semanticDataBatches
+ );
+
+ $inSemanticDataFetcher = new InSemanticDataFetcher( $this->getStore() );
+ $inSemanticData = $inSemanticDataFetcher->getSemanticData( DIWikiPage::newFromTitle( $main ) );
+
+ // When running sqlite, the database select returns an empty result which
+ // is probably due to some DB-prefix issues in MW's DatabaseBaseSqlite
+ // implementation and for non-sqlite see #212 / bug 62856
+ if ( $inSemanticData->getProperties() === [] ) {
+ $this->markTestSkipped(
+ "Skipping test either because of sqlite or MW-{$GLOBALS['wgVersion']} / bug 62856"
+ );
+ }
+
+ $this->assertThatSemanticDataValuesForPropertyAreSet(
+ $expectedRedirectAsWikiValue,
+ $inSemanticData
+ );
+ }
+
+ protected function assertThatCategoriesAreSet( $expectedCategoryAsWikiValue, $semanticDataBatches ) {
+
+ foreach ( $semanticDataBatches as $semanticData ) {
+ $this->semanticDataValidator->assertThatCategoriesAreSet(
+ $expectedCategoryAsWikiValue,
+ $semanticData
+ );
+ }
+ }
+
+ protected function assertThatPropertiesAreSet( $expectedSomeProperties, $semanticDataBatches ) {
+
+ foreach ( $semanticDataBatches as $semanticData ) {
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expectedSomeProperties,
+ $semanticData
+ );
+ }
+ }
+
+ protected function assertThatSemanticDataValuesForPropertyAreSet( $expected, $semanticData ) {
+
+ $runValueAssert = false;
+
+ foreach ( $semanticData->getProperties() as $property ) {
+
+ if ( $property->equals( $expected['property'] ) ) {
+
+ $runValueAssert = true;
+ $this->semanticDataValidator->assertThatPropertyValuesAreSet(
+ $expected,
+ $property,
+ $semanticData->getPropertyValues( $property )
+ );
+ }
+ }
+ // Issue #124 needs to be resolved first
+ // $this->assertTrue( $runValueAssert, __METHOD__ );
+ }
+
+ protected function createPageWithRedirectFor( $source, $target ) {
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( $source ) )
+ ->doEdit( "#REDIRECT [[{$target}]]" );
+
+ return $this->pageCreator->getPage();
+ }
+
+ protected function movePageToTargetRedirect( $page, $target ) {
+
+ $moveToTargetTitle = Title::newFromText( $target );
+
+ return $page->getTitle()->moveTo(
+ $moveToTargetTitle,
+ false,
+ 'create redirect',
+ true
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/TimeDataTypeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/TimeDataTypeTest.php
new file mode 100644
index 00000000..a4ddc179
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Import/TimeDataTypeTest.php
@@ -0,0 +1,281 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Import;
+
+use SMW\DIProperty;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\ByPageSemanticDataFinder;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-import
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class TimeDataTypeTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesAfterRun = true;
+
+ private $importedTitles = [];
+ private $runnerFactory;
+ private $titleValidator;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ if ( strpos( strtolower( $GLOBALS['smwgSparqlRepositoryConnector'] ), 'virtuoso' ) !== false ) {
+ $this->markTestIncomplete(
+ "Virtuoso will fail for '1 January 300 BC' with 'Virtuoso 22007 Error DT006: Cannot convert -0302-12-28Z to datetime : Incorrect month field length'"
+ );
+ }
+
+ $this->runnerFactory = UtilityFactory::getInstance()->newRunnerFactory();
+ $this->titleValidator = UtilityFactory::getInstance()->newValidatorFactory()->newTitleValidator();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+
+ $importRunner = $this->runnerFactory->newXmlImportRunner(
+ __DIR__ . '/'. 'Fixtures/' . 'TimeDataTypeTest-Mw-1-19-7.xml'
+ );
+
+ // Shoudl be fixed
+ if ( $GLOBALS['wgLanguageCode'] !== 'en' ) {
+ $this->markTestIncomplete( 'Skipping test because time/date comparison expects a (en) formatted string' );
+ }
+
+ if ( !$importRunner->setVerbose( true )->run() ) {
+ $importRunner->reportFailedImport();
+ $this->markTestIncomplete( 'Test was marked as incomplete because the data import failed' );
+ }
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->importedTitles );
+
+ parent::tearDown();
+ }
+
+ public function testImportOfDifferentDateWithAssortmentOfOutputConversion() {
+
+ $this->importedTitles = [
+ 'TimeDataTypeRegressionTest',
+ 'Property:Has query date',
+ 'Property:Has calendar date',
+ 'Property:Has date'
+ ];
+
+ $this->titleValidator->assertThatTitleIsKnown( $this->importedTitles );
+
+ $title = Title::newFromText( 'TimeDataTypeRegressionTest' );
+
+ $expectedCategoryAsWikiValue = [
+ 'property' => new DIProperty( '_INST' ),
+ 'propertyValues' => [
+ 'Regression test'
+ ]
+ ];
+
+ $expectedPropertiesFromImport = [
+ 'properties' => [
+ DIProperty::newFromUserLabel( 'Has date' ),
+ DIProperty::newFromUserLabel( 'Has calendar date' ),
+ DIProperty::newFromUserLabel( 'Has query date' ),
+ new DIProperty( '_ASK' ),
+ new DIProperty( '_MDAT' ),
+ new DIProperty( '_SKEY' ),
+ new DIProperty( '_SOBJ' ),
+ new DIProperty( '_INST' )
+ ]
+ ];
+
+ $expectedDateValuesAsISO = [
+ 'valueFormatter' => $this->setISO8601DateValueFormatter(),
+ 'property' => DIProperty::newFromUserLabel( 'Has query date' ),
+ 'propertyValues' => [
+ '2010-01-04T19:00:00',
+ '2011-06-08',
+ '1980-01-01',
+ '2000-02-11T10:00:00',
+ '2000-02-03'
+ ]
+ ];
+
+ $expectedDateValuesAsMediaWiki = [
+ 'valueFormatter' => $this->setMediaWikiDateValueFormatter(),
+ 'property' => DIProperty::newFromUserLabel( 'Has query date' ),
+ 'propertyValues' => [
+ '19:00, 4 January 2010',
+ '8 June 2011',
+ '1 January 1980',
+ '10:00, 11 February 2000',
+ '3 February 2000'
+ ]
+ ];
+
+ $expectedDateValuesAsWikiValue = [
+ 'valueFormatter' => $this->setWikiValueDateValueFormatter(),
+ 'property' => DIProperty::newFromUserLabel( 'Has query date' ),
+ 'propertyValues' => [
+ '4 January 2010 19:00:00',
+ '8 June 2011',
+ '1 January 1980',
+ '11 February 2000 10:00:00',
+ '3 February 2000'
+ ]
+ ];
+
+ // Note Windows vs Linux date conversion on PHP
+ // where 14000000000 BC is 2147483647 BC on Windows
+
+ $expectedCalendarSpecificDateValuesAsISO = [
+ 'valueFormatter' => $this->setISO8601DateValueFormatter(),
+ 'property' => DIProperty::newFromUserLabel( 'Has calendar date' ),
+ 'propertyValues' => [
+ '--301-12-28', // 1 January 300 BC
+ '--2147483647-01-01', // 2147483647 BC
+ '--14000000000-01-01',
+ '2000-02-24',
+ '1492-02-11'
+ ]
+ ];
+
+ $expectedCalendarSpecificDateValuesAsWikiValue = [
+ 'valueFormatter' => $this->setWikiValueDateValueFormatter(),
+ 'property' => DIProperty::newFromUserLabel( 'Has calendar date' ),
+ 'propertyValues' => [
+ '1 January 300 BC JL', // 1 January 300 BC
+ '2147483647 BC', // 2147483647 BC
+ '14000000000 BC',
+ '11 February 2000 JL',
+ '2 February 1492 JL'
+ ]
+ ];
+
+ $expectedCalendarSpecificDateValuesAsWikiValueWithGRCalendarModel = [
+ 'valueFormatter' => $this->setWikiValueDateWithGRCalendarModelValueFormatter(),
+ 'property' => DIProperty::newFromUserLabel( 'Has calendar date' ),
+ 'propertyValues' => [
+ '28 December 301 BC', // 1 January 300 BC
+ '2147483647 BC', // 2147483647 BC
+ '14000000000 BC',
+ '24 February 2000',
+ '11 February 1492'
+ ]
+ ];
+
+ $expectedCalendarSpecificDateValuesAsWikiValueWithJLCalendarModel = [
+ 'valueFormatter' => $this->setWikiValueDateWithJLCalendarModelValueFormatter(),
+ 'property' => DIProperty::newFromUserLabel( 'Has calendar date' ),
+ 'propertyValues' => [
+ '1 January 300 BC JL', // 1 January 300 BC
+ '2147483647 BC', // 2147483647 BC
+ '14000000000 BC',
+ '11 February 2000 JL',
+ '2 February 1492 JL'
+ ]
+ ];
+
+ $this->semanticDataFinder = new ByPageSemanticDataFinder;
+ $this->semanticDataFinder->setTitle( $title )->setStore( $this->getStore() );
+
+ $semanticDataBatches = [
+ $this->semanticDataFinder->fetchFromOutput(),
+ $this->semanticDataFinder->fetchFromStore()
+ ];
+
+ $expectedDateValuesBatches = [
+ $expectedDateValuesAsISO,
+ $expectedDateValuesAsMediaWiki,
+ $expectedDateValuesAsWikiValue,
+ $expectedCalendarSpecificDateValuesAsISO,
+ $expectedCalendarSpecificDateValuesAsWikiValue,
+ $expectedCalendarSpecificDateValuesAsWikiValueWithGRCalendarModel,
+ $expectedCalendarSpecificDateValuesAsWikiValueWithJLCalendarModel
+ ];
+
+ foreach ( $semanticDataBatches as $semanticData ) {
+
+ // Something changed in MW since 1.28 that causes a
+ // "SMW\Tests\Utils\Validators\SemanticDataValidator::assertContainsPropertyValues
+ // for '_INST' as '__sin' with (Regression test, Redirect test, Simple redirect test)
+ // Failed asserting that an array contains 'Lorem ipsum'." and since I'm not sure
+ // about the cause, this part is disabled and awaits an investigation
+
+ // $this->assertThatCategoriesAreSet(
+ // $expectedCategoryAsWikiValue,
+ // $semanticData
+ // );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet( $expectedPropertiesFromImport, $semanticData );
+ $this->assertBatchesOfDateValues( $expectedDateValuesBatches, $semanticData );
+ }
+
+ }
+
+ protected function assertBatchesOfDateValues( $assertionBatches, $semanticData ) {
+ foreach ( $assertionBatches as $singleAssertionBatch ) {
+ $this->assertThatDateValuesAreSet( $singleAssertionBatch, $semanticData );
+ }
+ }
+
+ protected function assertThatDateValuesAreSet( $expected, $semanticData ) {
+
+ $runDateValueAssert = false;
+
+ foreach ( $semanticData->getProperties() as $property ) {
+
+ if ( $property->findPropertyTypeID() === '_dat' && $property->equals( $expected['property'] ) ) {
+ $runDateValueAssert = true;
+ $this->semanticDataValidator->assertThatPropertyValuesAreSet(
+ $expected,
+ $property,
+ $semanticData->getPropertyValues( $property )
+ );
+ }
+
+ }
+
+ // Solve issue with single/testsuite DB setup first
+ // $this->assertTrue( $runDateValueAssert, __METHOD__ );
+ }
+
+ protected function setWikiValueDateValueFormatter() {
+ return function( $dataValue ) { return $dataValue->getWikiValue();
+ };
+ }
+
+ protected function setWikiValueDateWithGRCalendarModelValueFormatter() {
+ return function( $dataValue ) {
+ $dataValue->setOutputFormat( 'GR' );
+ return $dataValue->getWikiValue();
+ };
+ }
+
+ protected function setWikiValueDateWithJLCalendarModelValueFormatter() {
+ return function( $dataValue ) {
+ $dataValue->setOutputFormat( 'JL' );
+ return $dataValue->getWikiValue();
+ };
+ }
+
+ protected function setISO8601DateValueFormatter() {
+ return function( $dataValue ) { return $dataValue->getISO8601Date();
+ };
+ }
+
+ protected function setMediaWikiDateValueFormatter() {
+ return function( $dataValue ) { return $dataValue->getMediaWikiDate();
+ };
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php
new file mode 100644
index 00000000..c5dbf589
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php
@@ -0,0 +1,179 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Jobs;
+
+use SMW\ApplicationFactory;
+use SMW\Tests\MwDBaseUnitTestCase;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangePropagationDispatchJob extends MwDBaseUnitTestCase {
+
+ private $job = null;
+ private $pages = [];
+
+ private $mwHooksHandler;
+ private $pageCreator;
+
+ private $jobQueueRunner;
+ private $jobQueue;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+
+ $this->mwHooksHandler = $utilityFactory->newMwHooksHandler();
+
+ $this->mwHooksHandler->deregisterListedHooks();
+ $this->mwHooksHandler->invokeHooksFromRegistry();
+
+ $this->pageCreator = $utilityFactory->newPageCreator();
+
+ $this->jobQueue = ApplicationFactory::getInstance()->getJobQueue();
+
+ $this->jobQueueRunner = $utilityFactory->newRunnerFactory()->newJobQueueRunner();
+ $this->jobQueueRunner->setConnectionProvider( $this->getConnectionProvider() );
+ $this->jobQueueRunner->deleteAllJobs();
+
+ $this->testEnvironment->addConfiguration( 'smwgEnableUpdateJobs', true );
+ }
+
+ protected function tearDown() {
+
+ $this->testEnvironment->flushPages(
+ $this->pages
+ );
+
+ $this->testEnvironment->tearDown();
+ $this->mwHooksHandler->restoreListedHooks();
+
+ parent::tearDown();
+ }
+
+ public function testTriggerUpdateJob() {
+
+ $index = 1; //pass-by-reference
+
+ $this->getStore()->refreshData( $index, 1, false, true )->rebuild( $index );
+
+ $this->assertGreaterThan(
+ 0,
+ $this->jobQueue->getQueueSize( 'smw.update' )
+ );
+ }
+
+ public function testPropertyTypeChangeToCreateUpdateJob() {
+
+ $this->skipTestForDatabase(
+ 'sqlite', 'No idea why SQLite fails here with "Failed asserting that 0 is greater than 0".'
+ );
+
+ $this->skipTestForMediaWikiVersionLowerThan(
+ '1.27',
+ "Skipping test because JobQueue::getQueueSize only returns correct results on 1.27+"
+ );
+
+ $propertyPage = Title::newFromText( 'FooProperty', SMW_NS_PROPERTY );
+
+ $this->pageCreator
+ ->createPage( $propertyPage )
+ ->doEdit( '[[Has type::Page]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo', NS_MAIN ) )
+ ->doEdit( '[[FooProperty::SomePage]]' );
+
+ $this->pageCreator
+ ->createPage( $propertyPage )
+ ->doEdit( '[[Has type::Number]]' );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->jobQueue->disableCache();
+
+ $this->assertGreaterThan(
+ 0,
+ $this->jobQueue->getQueueSize( 'smw.changePropagationDispatch' )
+ );
+
+ $this->jobQueueRunner->setType( 'smw.changePropagationDispatch' )->run();
+
+ $this->jobQueue->disableCache();
+
+ $this->assertGreaterThan(
+ 0,
+ $this->jobQueue->getQueueSize( 'smw.update' )
+ );
+
+ $this->jobQueueRunner->setType( 'smw.update' )->run();
+
+ foreach ( $this->jobQueueRunner->getStatus() as $status ) {
+ $this->assertTrue( $status['status'] );
+ }
+
+ $this->pages = [
+ $propertyPage,
+ Title::newFromText( 'Foo' )
+ ];
+ }
+
+ public function testCategoryChangeToCreateUpdateJob() {
+
+ $this->skipTestForDatabase(
+ 'sqlite', 'No idea why SQLite fails here with "Failed asserting that 0 is greater than 0".'
+ );
+
+ $this->skipTestForMediaWikiVersionLowerThan(
+ '1.27',
+ "Skipping test because JobQueue::getQueueSize only returns correct results on 1.27+"
+ );
+
+ $category = Title::newFromText( 'FooCat', NS_CATEGORY );
+
+ $this->pageCreator
+ ->createPage( $category )
+ ->doEdit( '...' );
+
+ $this->pageCreator
+ ->createPage( $category )
+ ->doEdit( '[[Category:Bar]]' );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->jobQueue->disableCache();
+
+ $this->assertGreaterThan(
+ 0,
+ $this->jobQueue->getQueueSize( 'smw.changePropagationDispatch' )
+ );
+
+ $this->jobQueueRunner->setType( 'smw.changePropagationDispatch' )->run();
+
+ $this->jobQueue->disableCache();
+
+ $this->assertGreaterThan(
+ 0,
+ $this->jobQueue->getQueueSize( 'smw.update' )
+ );
+
+ $this->jobQueueRunner->setType( 'smw.update' )->run();
+
+ foreach ( $this->jobQueueRunner->getStatus() as $status ) {
+ $this->assertTrue( $status['status'] );
+ }
+
+ $this->pages = [
+ $category
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/UpdateJobRoundtripTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/UpdateJobRoundtripTest.php
new file mode 100644
index 00000000..d4c43776
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/Jobs/UpdateJobRoundtripTest.php
@@ -0,0 +1,231 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki\Jobs;
+
+use Job;
+use SMW\ApplicationFactory;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class UpdateJobRoundtripTest extends MwDBaseUnitTestCase {
+
+ private $job = null;
+ private $applicationFactory;
+
+ private $deletePoolOfPages = [];
+ private $runnerFactory;
+
+ private $mwHooksHandler;
+ private $semanticDataValidator;
+
+ private $pageDeleter;
+ private $pageCreator;
+
+ private $jobQueueRunner;
+ private $jobQueue;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = UtilityFactory::getInstance();
+
+ $this->mwHooksHandler = $utilityFactory->newMwHooksHandler();
+
+ $this->mwHooksHandler
+ ->deregisterListedHooks()
+ ->invokeHooksFromRegistry();
+
+ $this->semanticDataValidator = $utilityFactory->newValidatorFactory()->newSemanticDataValidator();
+ $this->pageDeleter = $utilityFactory->newPageDeleter();
+ $this->pageCreator = $utilityFactory->newPageCreator();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ // FIXME Because of SQLStore::Writer::changeTitle
+ $GLOBALS['smwgEnableUpdateJobs'] = true;
+
+ $settings = [
+ 'smwgEnableUpdateJobs' => true
+ ];
+
+ foreach ( $settings as $key => $value ) {
+ $this->applicationFactory->getSettings()->set( $key, $value );
+ }
+
+ $this->jobQueue = $this->applicationFactory->getJobQueue();
+
+ $this->jobQueueRunner = $utilityFactory->newRunnerFactory()->newJobQueueRunner();
+ $this->jobQueueRunner->setConnectionProvider( $this->getConnectionProvider() );
+ $this->jobQueueRunner->deleteAllJobs();
+ }
+
+ protected function tearDown() {
+
+ $this->pageDeleter->doDeletePoolOfPages(
+ $this->deletePoolOfPages
+ );
+
+ $this->applicationFactory->clear();
+ $this->mwHooksHandler->restoreListedHooks();
+
+ parent::tearDown();
+ }
+
+ public function testPageMoveTriggersUpdateJob() {
+
+ $oldTitle = Title::newFromText( __METHOD__ . '-old' );
+ $newTitle = Title::newFromText( __METHOD__ . '-new' );
+
+ $this->pageCreator
+ ->createPage( $oldTitle )
+ ->doEdit( '[[Has jobqueue test::UpdateJob]]' );
+
+ $this->pageCreator
+ ->getPage()
+ ->getTitle()
+ ->moveTo( $newTitle, false, 'test', true );
+
+ // Execute the job directly
+ // $this->assertJob( 'SMW\UpdateJob' );
+
+ $this->assertTrue(
+ $oldTitle->isRedirect()
+ );
+
+ $this->pageDeleter->deletePage(
+ $oldTitle
+ );
+ }
+
+ public function testSQLStoreRefreshDataTriggersUpdateJob() {
+
+ $index = 1; //pass-by-reference
+
+ $this->getStore()->refreshData( $index, 1, false, true )->rebuild( $index );
+ $this->assertJob( 'smw.update' );
+ }
+
+ /**
+ * @dataProvider jobFactoryProvider
+ */
+ public function testJobFactory( $jobName, $type ) {
+
+ $job = Job::factory(
+ $jobName,
+ Title::newFromText( __METHOD__ . $jobName ),
+ []
+ );
+
+ $this->assertJob( $type, $job );
+ }
+
+ public function jobFactoryProvider() {
+
+ $provider = [];
+
+ $provider[] = [ 'SMW\UpdateJob', 'smw.update' ];
+ $provider[] = [ 'SMW\UpdateJob', 'SMW\UpdateJob' ];
+ $provider[] = [ 'SMWUpdateJob', 'SMW\UpdateJob' ];
+
+ $provider[] = [ 'SMW\RefreshJob', 'smw.refresh' ];
+ $provider[] = [ 'SMW\RefreshJob', 'SMW\RefreshJob' ];
+ $provider[] = [ 'SMWRefreshJob', 'SMW\RefreshJob' ];
+
+ return $provider;
+ }
+
+ public function titleProvider() {
+
+ $provider = [];
+
+ // #0 Simple property reference
+ $provider[] = [ [
+ 'title' => Title::newFromText( __METHOD__ . '-foo' ),
+ 'edit' => '{{#set:|DeferredJobFoo=DeferredJobBar}}'
+ ], [
+ 'title' => Title::newFromText( __METHOD__ . '-bar' ),
+ 'edit' => '{{#set:|DeferredJobFoo=DeferredJobBar}}'
+ ]
+ ];
+
+ // #1 Source page in-property reference
+ $title = Title::newFromText( __METHOD__ . '-foo' );
+
+ $provider[] = [ [
+ 'title' => $title,
+ 'edit' => ''
+ ], [
+ 'title' => Title::newFromText( __METHOD__ . '-bar' ),
+ 'edit' => '{{#set:|DeferredJobFoo=' . $title->getPrefixedText() . '}}'
+ ]
+ ];
+
+ return $provider;
+ }
+
+ protected function assertJob( $type, Job &$job = null ) {
+
+ if ( $job === null ) {
+ $job = $this->jobQueueRunner->pop_type( $type );
+ }
+
+ if ( !$job ) {
+ $this->markTestSkipped( "Required a {$type} JobQueue entry" );
+ }
+
+ $this->job = $job;
+
+ $this->assertInstanceOf( 'Job', $job );
+ $this->assertTrue( $job->run() );
+ }
+
+ /**
+ * Issue 617
+ */
+ public function testNoInfiniteUpdateJobsForCircularRedirect() {
+
+ $this->skipTestForMediaWikiVersionLowerThan( '1.20' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo-A' ) )
+ ->doEdit( '[[Foo-A::{{PAGENAME}}]] {{#ask: [[Foo-A::{{PAGENAME}}]] }}' )
+ ->doEdit( '#REDIRECT [[Foo-B]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo-B' ) )
+ ->doEdit( '#REDIRECT [[Foo-C]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo-C' ) )
+ ->doEdit( '#REDIRECT [[Foo-A]]' );
+
+ $this->jobQueueRunner
+ ->setType( 'SMW\UpdateJob' )
+ ->run();
+
+ foreach ( $this->jobQueueRunner->getStatus() as $status ) {
+ $this->assertTrue( $status['status'] );
+ }
+
+ $this->assertTrue(
+ Title::newFromText( 'Foo-A' )->isRedirect()
+ );
+
+ $this->deletePoolOfPages = [
+ Title::newFromText( 'Foo-A' ),
+ Title::newFromText( 'Foo-B' ),
+ Title::newFromText( 'Foo-C' )
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateEmptyParserOutputDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateEmptyParserOutputDBIntegrationTest.php
new file mode 100644
index 00000000..e2a2d0b1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateEmptyParserOutputDBIntegrationTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use LinksUpdate;
+use ParserOutput;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\PageCreator;
+use Title;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-databaseless
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class LinksUpdateEmptyParserOutputDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ public function testDoUpdate() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $subject = DIWikiPage::newFromTitle( $title );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $title )
+ ->doEdit( '[[Has some property::LinksUpdateConstructedOnEmptyParserOutput]]' );
+
+ $propertiesCountBeforeUpdate = count( $this->getStore()->getSemanticData( $subject )->getProperties() );
+
+ $linksUpdate = new LinksUpdate( $title, new ParserOutput() );
+ $linksUpdate->doUpdate();
+
+
+ $this->assertCount(
+ $propertiesCountBeforeUpdate,
+ $this->getStore()->getSemanticData( $subject )->getProperties()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateSQLStoreDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateSQLStoreDBIntegrationTest.php
new file mode 100644
index 00000000..ef819d8b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateSQLStoreDBIntegrationTest.php
@@ -0,0 +1,249 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use LinksUpdate;
+use ParserOutput;
+use Revision;
+use SMW\ContentParser;
+use SMW\DIWikiPage;
+use SMW\ParserData;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\PageCreator;
+use Title;
+use UnexpectedValueException;
+use User;
+use WikiPage;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class LinksUpdateSQLStoreDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesBeforeRun = true;
+
+ private $title = null;
+ private $mwHooksHandler;
+ private $semanticDataValidator;
+ private $pageDeleter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgPageSpecialProperties',
+ [ '_MDAT' ]
+ );
+
+ $this->mwHooksHandler = $this->testEnvironment->getUtilityFactory()->newMwHooksHandler();
+
+ $this->mwHooksHandler->deregisterListedHooks();
+ $this->mwHooksHandler->invokeHooksFromRegistry();
+
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ $this->pageDeleter = $this->testEnvironment->getUtilityFactory()->newPageDeleter();
+ }
+
+ public function tearDown() {
+
+ $this->mwHooksHandler->restoreListedHooks();
+
+ if ( $this->title !== null ) {
+ $this->pageDeleter->deletePage( $this->title );
+ }
+
+ parent::tearDown();
+ }
+
+ public function testPageCreationAndRevisionHandlingBeforeLinksUpdate() {
+
+ $this->title = Title::newFromText( __METHOD__ );
+
+ $beforeAlterationRevId = $this->createSinglePageWithAnnotations();
+ $this->assertSemanticDataBeforeContentAlteration();
+
+ $afterAlterationRevId = $this->alterPageContentToCreateNewRevisionWithoutAnnotations();
+ $this->assertSemanticDataAfterContentAlteration();
+
+ $this->assertNotSame(
+ $beforeAlterationRevId,
+ $afterAlterationRevId
+ );
+ }
+
+ /**
+ * @depends testPageCreationAndRevisionHandlingBeforeLinksUpdate
+ * @dataProvider propertyCountProvider
+ */
+ public function testLinksUpdateAndVerifyStoreUpdate( $expected ) {
+
+ $this->title = Title::newFromText( __METHOD__ );
+
+ $beforeAlterationRevId = $this->createSinglePageWithAnnotations();
+ $afterAlterationRevId = $this->alterPageContentToCreateNewRevisionWithoutAnnotations();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->fetchRevisionAndRunLinksUpdater(
+ $expected['beforeAlterationRevId'],
+ $beforeAlterationRevId
+ );
+
+ $this->fetchRevisionAndRunLinksUpdater(
+ $expected['afterAlterationRevId'],
+ $afterAlterationRevId
+ );
+ }
+
+ protected function createSinglePageWithAnnotations() {
+ $pageCreator = new PageCreator();
+ $pageCreator->createPage( $this->title )->doEdit( 'Add user property Aa and Fuyu {{#set:|Aa=Bb|Fuyu=Natsu}}' );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ return $pageCreator->getPage()->getRevision()->getId();
+ }
+
+ protected function alterPageContentToCreateNewRevisionWithoutAnnotations() {
+ $pageCreator = new PageCreator();
+ $pageCreator->createPage( $this->title )->doEdit( 'No annotations' );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ return $pageCreator->getPage()->getRevision()->getId();
+ }
+
+ protected function assertSemanticDataBeforeContentAlteration() {
+
+ $wikiPage = WikiPage::factory( $this->title );
+ $revision = $wikiPage->getRevision();
+
+ $parserData = $this->retrieveAndLoadData();
+ $this->assertCount( 3, $parserData->getSemanticData()->getProperties() );
+
+ $this->assertEquals(
+ $parserData->getSemanticData()->getHash(),
+ $this->retrieveAndLoadData( $revision->getId() )->getSemanticData()->getHash(),
+ 'Asserts that data are equals with or without a revision'
+ );
+
+ $this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
+ 4,
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) ),
+ 'Asserts property Aa, Fuyu, _SKEY, and _MDAT exists'
+ );
+ }
+
+ protected function assertSemanticDataAfterContentAlteration() {
+ $this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
+ 2,
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) ),
+ 'Asserts property _SKEY and _MDAT exists'
+ );
+ }
+
+ protected function fetchRevisionAndRunLinksUpdater( array $expected, $revId ) {
+
+ $parserData = $this->retrieveAndLoadData( $revId );
+
+ // Status before the update
+ $this->assertPropertyCount( $expected['poBefore'], $expected['storeBefore'], $parserData );
+
+ $this->runLinksUpdater( $this->title, $parserData->getOutput() );
+
+ // Status after the update
+ $this->assertPropertyCount( $expected['poAfter'], $expected['storeAfter'], $parserData );
+ }
+
+ protected function assertPropertyCount( $poExpected, $storeExpected, $parserData ) {
+ $this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
+ $poExpected['count'],
+ $parserData->getSemanticData(),
+ $poExpected['msg']
+ );
+
+ $this->semanticDataValidator->assertThatSemanticDataHasPropertyCountOf(
+ $storeExpected['count'],
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) ),
+ $storeExpected['msg']
+ );
+ }
+
+ protected function runLinksUpdater( Title $title, $parserOutput ) {
+ $linksUpdate = new LinksUpdate( $title, $parserOutput );
+ $linksUpdate->doUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ protected function retrieveAndLoadData( $revId = null ) {
+
+ $revision = $revId ? Revision::newFromId( $revId ) : null;
+
+ $contentParser = new ContentParser( $this->title );
+ $parserOutput = $contentParser->setRevision( $revision )->parse()->getOutput();
+ $parserOutput->setExtensionData( ParserData::OPT_FORCED_UPDATE, true );
+
+ if ( $parserOutput instanceof ParserOutput ) {
+ return new ParserData( $this->title, $parserOutput );
+ }
+
+ throw new UnexpectedValueException( 'ParserOutput is missing' );
+ }
+
+ public function propertyCountProvider() {
+
+ // Property _SKEY is always present even within an empty container
+ // po = ParserOutput, before means prior LinksUpdate
+
+ $provider = [];
+
+ $provider[] = [ [
+ 'beforeAlterationRevId' => [
+ 'poBefore' => [
+ 'count' => 3,
+ 'msg' => 'Asserts property Aa, Fuyu, and _SKEY exists before the update'
+ ],
+ 'storeBefore' => [
+ 'count' => 2,
+ 'msg' => 'Asserts property _SKEY and _MDAT exists in Store before the update'
+ ],
+ 'poAfter' => [
+ 'count' => 4,
+ 'msg' => 'Asserts property Aa, Fuyu, _SKEY, and _MDAT exists after the update'
+ ],
+ 'storeAfter' => [
+ 'count' => 4,
+ 'msg' => 'Asserts property Aa, Fuyu, _SKEY, and _MDAT exists after the update'
+ ]
+ ],
+ 'afterAlterationRevId' => [
+ 'poBefore' => [
+ 'count' => 0,
+ 'msg' => 'Asserts no property exists before the update'
+ ],
+ 'storeBefore' => [
+ 'count' => 4,
+ 'msg' => 'Asserts property Aa, Fuyu, _SKEY, and _MDAT from the previous state as no update has been made yet'
+ ],
+ 'poAfter' => [
+ 'count' => 0,
+ 'msg' => 'Asserts property _MDAT exists after the update'
+ ],
+ 'storeAfter' => [
+ 'count' => 2,
+ 'msg' => 'Asserts property _SKEY, _MDAT exists after the update'
+ ]
+ ]
+ ] ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateTest.php
new file mode 100644
index 00000000..d78ce871
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/LinksUpdateTest.php
@@ -0,0 +1,216 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class LinksUpdateTest extends MwDBaseUnitTestCase {
+
+ protected $destroyDatabaseTablesBeforeRun = true;
+
+ private $title = null;
+ private $applicationFactory;
+ private $mwHooksHandler;
+ private $semanticDataValidator;
+ private $pageDeleter;
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mwHooksHandler = $this->testEnvironment->getUtilityFactory()->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+ $this->mwHooksHandler->invokeHooksFromRegistry();
+
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ $this->pageCreator = $this->testEnvironment->getUtilityFactory()->newPageCreator();
+ $this->pageDeleter = $this->testEnvironment->getUtilityFactory()->newPageDeleter();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->testEnvironment->addConfiguration( 'smwgPageSpecialProperties', [ '_MDAT' ] );
+
+ $this->title = Title::newFromText( __METHOD__ );
+ }
+
+ public function tearDown() {
+ $this->applicationFactory->clear();
+ $this->mwHooksHandler->restoreListedHooks();
+
+ $this->testEnvironment->flushPages( [ $this->title ] );
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testUpdateToSetPredefinedAnnotations() {
+
+ $this->pageCreator
+ ->createPage( $this->title );
+
+ $semanticData = $this->getStore()->getSemanticData(
+ DIWikiPage::newFromTitle( $this->title )
+ );
+
+ $this->assertCount(
+ 2,
+ $semanticData->getProperties()
+ );
+
+ $expected = [
+ 'propertyKeys' => [ '_SKEY', '_MDAT' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $semanticData
+ );
+ }
+
+ /**
+ * @depends testUpdateToSetPredefinedAnnotations
+ */
+ public function testDoUpdateUsingUserdefinedAnnotations() {
+
+ $this->pageCreator
+ ->createPage( $this->title )
+ ->doEdit( '[[HasFirstLinksUpdatetest::testDoUpdate]] [[HasSecondLinksUpdatetest::testDoUpdate]]' );
+
+ $parserData = $this->applicationFactory->newParserData(
+ $this->title,
+ $this->pageCreator->getEditInfo()->output
+ );
+
+ $contentParser = $this->applicationFactory->newContentParser( $this->title );
+ $contentParser->parse();
+
+ $parsedParserData = $this->applicationFactory->newParserData(
+ $this->title,
+ $contentParser->getOutput()
+ );
+
+ $this->assertCount(
+ 4,
+ $parserData->getSemanticData()->getProperties()
+ );
+
+ $this->assertCount(
+ 4,
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) )->getProperties()
+ );
+
+ /**
+ * See #347 and LinksUpdateConstructed
+ */
+ $linksUpdate = new \LinksUpdate( $this->title, new \ParserOutput() );
+ $linksUpdate->doUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ /**
+ * Asserts that before and after the update, the SemanticData container
+ * holds the same amount of properties despite the fact that the ParserOutput
+ * was invoked empty
+ */
+ $semanticData = $this->getStore()->getSemanticData(
+ DIWikiPage::newFromTitle( $this->title )
+ );
+
+ $this->assertCount(
+ 4,
+ $semanticData->getProperties()
+ );
+
+ $expected = [
+ 'propertyKeys' => [ '_SKEY', '_MDAT', 'HasFirstLinksUpdatetest', 'HasSecondLinksUpdatetest' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $semanticData
+ );
+
+ return $this->pageCreator->getPage()->getRevision();
+ }
+
+ /**
+ * @depends testDoUpdateUsingUserdefinedAnnotations
+ */
+ public function testDoUpdateUsingNoAnnotations( $firstRunRevision ) {
+
+ $this->pageCreator
+ ->createPage( $this->title )
+ ->doEdit( 'no annotation' );
+
+ $this->assertNotSame(
+ $firstRunRevision,
+ $this->pageCreator->getPage()->getRevision()
+ );
+
+ $contentParser = $this->applicationFactory->newContentParser( $this->title );
+ $contentParser->parse();
+
+ $parserData = $this->applicationFactory->newParserData(
+ $this->title,
+ $contentParser->getOutput()
+ );
+
+ if ( count( $parserData->getSemanticData()->getProperties() ) != 0 ) {
+ $this->markTestSkipped( "Something changed with MW 1.28 and I'm too lazy to investigate." );
+ }
+
+ $this->assertCount(
+ 0,
+ $parserData->getSemanticData()->getProperties()
+ );
+
+ $this->assertCount(
+ 2,
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) )->getProperties()
+ );
+
+ return $firstRunRevision;
+ }
+
+ /**
+ * @depends testDoUpdateUsingNoAnnotations
+ */
+ public function testReparseFirstRevision( $firstRunRevision ) {
+
+ $contentParser = $this->applicationFactory->newContentParser( $this->title );
+ $contentParser->setRevision( $firstRunRevision );
+ $contentParser->parse();
+
+ $parserData = $this->applicationFactory->newParserData(
+ $this->title,
+ $contentParser->getOutput()
+ );
+
+ $semanticData = $parserData->getSemanticData();
+
+ $this->assertCount(
+ 3,
+ $semanticData->getProperties()
+ );
+
+ $expected = [
+ 'propertyKeys' => [ '_SKEY', 'HasFirstLinksUpdatetest', 'HasSecondLinksUpdatetest' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $semanticData
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MWNamespaceCanonicalNameMatchTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MWNamespaceCanonicalNameMatchTest.php
new file mode 100644
index 00000000..b76cc65f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MWNamespaceCanonicalNameMatchTest.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use MWNamespace;
+use SMW\NamespaceManager;
+use SMW\Settings;
+use SMW\Tests\Utils\MwHooksHandler;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class MWNamespaceCanonicalNameMatchTest extends \PHPUnit_Framework_TestCase {
+
+ private $mwHooksHandler;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mwHooksHandler = new MwHooksHandler();
+ }
+
+ public function tearDown() {
+ $this->mwHooksHandler->restoreListedHooks();
+
+ parent::tearDown();
+ }
+
+ public function testRunNamespaceManagerWithNoConstantsDefined() {
+
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $default = [
+ 'smwgNamespacesWithSemanticLinks' => [],
+ 'wgNamespacesWithSubpages' => [],
+ 'wgExtraNamespaces' => [],
+ 'wgNamespaceAliases' => [],
+ 'wgContentNamespaces' => [],
+ 'wgNamespacesToBeSearchedDefault' => [],
+ 'wgLanguageCode' => 'en'
+ ];
+
+ $instance = $this->getMockBuilder( '\SMW\NamespaceManager' )
+ ->setMethods( [ 'isDefinedConstant' ] )
+ ->getMock();
+
+ $instance->expects( $this->atLeastOnce() )
+ ->method( 'isDefinedConstant' )
+ ->will( $this->returnValue( false ) );
+
+ $instance->init( $default );
+ }
+
+ public function testCanonicalNames() {
+
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $count = 0;
+ $index = NamespaceManager::buildNamespaceIndex( Settings::newFromGlobals()->get( 'smwgNamespaceIndex' ) );
+ $names = NamespaceManager::getCanonicalNames();
+
+ $this->assertInternalType( 'array', $names );
+ $this->assertInternalType( 'array', $index );
+
+ foreach ( $index as $ns => $idx ) {
+
+ $mwNamespace = MWNamespace::getCanonicalName( $idx );
+
+ if ( $mwNamespace && isset( $names[$idx] ) ) {
+ $this->assertEquals( $mwNamespace, $names[$idx] );
+ $count++;
+ }
+ }
+
+ $this->assertCount(
+ $count,
+ $names,
+ "Asserts that expected amount of cannonical names have been verified"
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MediaWikiIntegrationForRegisteredHookTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MediaWikiIntegrationForRegisteredHookTest.php
new file mode 100644
index 00000000..073e7fde
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/MediaWikiIntegrationForRegisteredHookTest.php
@@ -0,0 +1,176 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use RequestContext;
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\ParserData;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Tests\Utils\PageDeleter;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+use WikiPage;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class MediaWikiIntegrationForRegisteredHookTest extends MwDBaseUnitTestCase {
+
+ private $title;
+ private $semanticDataValidator;
+ private $applicationFactory;
+ private $mwHooksHandler;
+ private $pageDeleter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mwHooksHandler = UtilityFactory::getInstance()->newMwHooksHandler();
+
+ $this->mwHooksHandler
+ ->deregisterListedHooks()
+ ->invokeHooksFromRegistry();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $settings = [
+ 'smwgPageSpecialProperties' => [ '_MDAT' ],
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgMainCacheType' => 'hash',
+ 'smwgAutoRefreshOnPurge' => true
+ ];
+
+ foreach ( $settings as $key => $value ) {
+ $this->applicationFactory->getSettings()->set( $key, $value );
+ }
+
+ $this->pageDeleter = new PageDeleter();
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+ $this->mwHooksHandler->restoreListedHooks();
+
+ $this->pageDeleter->deletePage( $this->title );
+
+ parent::tearDown();
+ }
+
+ public function testPagePurge() {
+
+ $cacheFactory = $this->applicationFactory->newCacheFactory();
+ $cache = $cacheFactory->newFixedInMemoryCache();
+
+ $this->applicationFactory->registerObject( 'Cache', $cache );
+
+ $this->title = Title::newFromText( __METHOD__ );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $this->title )
+ ->doEdit( '[[Has function hook test::page purge]]' );
+
+ $key = $cacheFactory->getPurgeCacheKey( $this->title->getArticleID() );
+
+ $pageCreator
+ ->getPage()
+ ->doPurge();
+
+ $this->assertTrue(
+ $cache->fetch( $key )
+ );
+ }
+
+ public function testPageDelete() {
+
+ $this->title = Title::newFromText( __METHOD__ );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $this->title )
+ ->doEdit( '[[Has function hook test::page delete]]' );
+
+ $this->semanticDataValidator->assertThatSemanticDataIsNotEmpty(
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) )
+ );
+
+ $this->pageDeleter->deletePage( $this->title );
+
+ $this->semanticDataValidator->assertThatSemanticDataIsEmpty(
+ $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) )
+ );
+ }
+
+ public function testEditPageToGetNewRevision() {
+
+ $this->title = Title::newFromText( __METHOD__ );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $this->title )
+ ->doEdit( '[[EditPageToGetNewRevisionHookTest::Foo]]' );
+
+ $parserOutput = $pageCreator->getEditInfo()->output;
+
+ $this->assertInstanceOf(
+ 'ParserOutput',
+ $parserOutput
+ );
+
+ $parserData = new ParserData(
+ $this->title,
+ $parserOutput
+ );
+
+ $expected = [
+ 'propertyKeys' => [ '_SKEY', '_MDAT', 'EditPageToGetNewRevisionHookTest' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testOnOutputPageParserOutputeOnDatabase() {
+
+ $this->title = Title::newFromText( __METHOD__ );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $this->title )
+ ->doEdit( '[[Has function hook test::output page]]' );
+
+ $parserOutput = $pageCreator->getEditInfo()->output;
+
+ $this->assertInstanceOf(
+ 'ParserOutput',
+ $parserOutput
+ );
+
+ $context = new RequestContext();
+ $context->setTitle( $this->title );
+
+ // Use of OutputPage::addParserOutputNoText was deprecated in MediaWiki 1.24
+ if ( method_exists( $context->getOutput(), 'addParserOutputMetadata' ) ) {
+ $context->getOutput()->addParserOutputMetadata( $parserOutput );
+ } else {
+ $context->getOutput()->addParserOutputNoText( $parserOutput );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/PredefinedPropertyAnnotationDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/PredefinedPropertyAnnotationDBIntegrationTest.php
new file mode 100644
index 00000000..7151de41
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/PredefinedPropertyAnnotationDBIntegrationTest.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDITime as DITime;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-databaseless
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class PredefinedPropertyAnnotationDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $semanticDataValidator;
+ private $applicationFactory;
+ private $dataValueFactory;
+ private $mwHooksHandler;
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mwHooksHandler = UtilityFactory::getInstance()->newMwHooksHandler();
+
+ $this->mwHooksHandler
+ ->deregisterListedHooks()
+ ->invokeHooksFromRegistry();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ $this->pageCreator = UtilityFactory::getInstance()->newPageCreator();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+ $this->mwHooksHandler->restoreListedHooks();
+
+ parent::tearDown();
+ }
+
+ public function testPredefinedModificationDatePropertyAndChangedDefaultsortForNewPage() {
+
+ $this->applicationFactory->getSettings()->set( 'smwgPageSpecialProperties', [ '_MDAT' ] );
+
+ $title = Title::newFromText( __METHOD__ );
+ $subject = DIWikiPage::newFromTitle( $title );
+
+ $this->pageCreator
+ ->createPage( $title, '{{DEFAULTSORT:SortForFoo}}' );
+
+ $dvPageModificationTime = $this->dataValueFactory->newDataValueByItem(
+ DITime::newFromTimestamp( $this->pageCreator->getPage()->getTimestamp() )
+ );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_MDAT', '_SKEY' ],
+ 'propertyValues' => [ $dvPageModificationTime->getISO8601Date(), 'SortForFoo' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $this->getStore()->getSemanticData( $subject )
+ );
+ }
+
+ public function testAddedCategoryAndChangedDefaultsortWithoutPredefinedPropertiesForNewPage() {
+
+ $this->applicationFactory->getSettings()->set( 'smwgPageSpecialProperties', [] );
+
+ $title = Title::newFromText( __METHOD__ );
+ $subject = DIWikiPage::newFromTitle( $title );
+
+ $this->pageCreator
+ ->createPage( $title )
+ ->doEdit( '{{DEFAULTSORT:SortForFoo}} [[Category:SingleCategory]]' );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_SKEY', '_INST' ],
+ 'propertyValues' => [ 'SortForFoo', 'SingleCategory' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $this->getStore()->getSemanticData( $subject )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/RedirectTargetFinderIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/RedirectTargetFinderIntegrationTest.php
new file mode 100644
index 00000000..1cccce0e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/RedirectTargetFinderIntegrationTest.php
@@ -0,0 +1,260 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMW\Tests\PHPUnitCompat;
+use Title;
+
+/**
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-databas
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class RedirectTargetFinderIntegrationTest extends MwDBaseUnitTestCase {
+
+ use PHPUnitCompat;
+
+ private $deletePoolOfPages = [];
+
+ private $pageCreator;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgEnabledDeferredUpdate',
+ false
+ );
+
+ $this->pageCreator = UtilityFactory::getInstance()->newPageCreator();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+
+ // #3414
+ // NameTableAccessException: Expected unused ID from database insert for
+ // 'mw-changed-redirect-target' into 'change_tag_def',
+ $this->testEnvironment->resetMediaWikiService( 'NameTableStoreFactory' );
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+
+ $pageDeleter
+ ->doDeletePoolOfPages( $this->deletePoolOfPages );
+
+ parent::tearDown();
+ }
+
+ public function testRedirectParseUsingManualRedirect() {
+
+ $target = Title::newFromText( 'RedirectParseUsingManualRedirect' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( __METHOD__ ) )
+ ->doEdit( '#REDIRECT [[RedirectParseUsingManualRedirect]]' );
+
+ $expected = [
+ new DIProperty( '_REDI' )
+ ];
+
+ $this->semanticDataValidator->assertHasProperties(
+ $expected,
+ $this->getStore()->getInProperties( DIWikiPage::newFromTitle( $target ) )
+ );
+
+ $this->deletePoolOfPages = [
+ __METHOD__,
+ 'RedirectParseUsingManualRedirect'
+ ];
+ }
+
+ public function testRedirectParseUsingMoveToPage() {
+
+ $target = Title::newFromText( 'RedirectParseUsingMoveToPage' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( __METHOD__ ) );
+
+ $this->pageCreator
+ ->getPage()
+ ->getTitle()
+ ->moveTo( $target, false, 'test', true );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $expected = [
+ new DIProperty( '_REDI' )
+ ];
+
+ $this->semanticDataValidator->assertHasProperties(
+ $expected,
+ $this->getStore()->getInProperties( DIWikiPage::newFromTitle( $target ) )
+ );
+
+ $this->deletePoolOfPages = [
+ __METHOD__,
+ 'RedirectParseUsingMoveToPage'
+ ];
+ }
+
+ public function testManualRemovalOfRedirectTarget() {
+
+ $source = DIWikiPage::newFromTitle(
+ Title::newFromText( __METHOD__ )
+ );
+
+ $target = DIWikiPage::newFromTitle(
+ Title::newFromText( 'ManualRemovalOfRedirectTarget' )
+ );
+
+ $target->getSortKey();
+
+ $this->pageCreator
+ ->createPage( $source->getTitle() )
+ ->doEdit( '#REDIRECT [[Property:ManualRemovalOfRedirectTarget-NotTheRealTarget]]' )
+ ->doEdit( '#REDIRECT [[ManualRemovalOfRedirectTarget]]' );
+
+ $expected = [
+ new DIProperty( '_REDI' )
+ ];
+
+ $this->assertEquals(
+ $target,
+ $this->getStore()->getRedirectTarget( $source )
+ );
+
+ $this->semanticDataValidator->assertHasProperties(
+ $expected,
+ $this->getStore()->getInProperties( $target )
+ );
+
+ $this->pageCreator
+ ->createPage( $source->getTitle() )
+ ->doEdit( 'removed redirect target' );
+
+ $this->assertEquals(
+ $source,
+ $this->getStore()->getRedirectTarget( $source )
+ );
+
+ $this->assertEmpty(
+ $this->getStore()->getInProperties( $target )
+ );
+
+ $this->deletePoolOfPages = [
+ __METHOD__,
+ 'ManualRemovalOfRedirectTarget'
+ ];
+ }
+
+ public function testDeepRedirectTargetResolverToFindTarget() {
+
+ $this->skipTestForMediaWikiVersionLowerThan(
+ '1.20',
+ "Skipping test because expected target isn't resolved correctly on 1.19"
+ );
+
+ $source = Title::newFromText( 'DeepRedirectTargetResolverToFindTarget' );
+
+ $this->pageCreator
+ ->createPage( $source )
+ ->doEdit( '#REDIRECT [[DeepRedirectTargetResolverToFindTarget/1]]' );
+
+ $intermediateTarget = Title::newFromText( 'DeepRedirectTargetResolverToFindTarget/2' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'DeepRedirectTargetResolverToFindTarget/1' ) )
+ ->getPage()
+ ->getTitle()
+ ->moveTo( $intermediateTarget, false, 'redirect test', true );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'DeepRedirectTargetResolverToFindTarget/2' ) )
+ ->doEdit( '#REDIRECT [[DeepRedirectTargetResolverToFindTarget/3]]' );
+
+ $target = Title::newFromText( 'DeepRedirectTargetResolverToFindTarget/3' );
+
+ $deepRedirectTargetResolver = ApplicationFactory::getInstance()
+ ->newMwCollaboratorFactory()
+ ->newDeepRedirectTargetResolver();
+
+ $this->assertEquals(
+ $target->getDBKey(),
+ $deepRedirectTargetResolver->findRedirectTargetFor( $source )->getDBKey()
+ );
+
+ $this->assertEquals(
+ $target->getDBKey(),
+ $this->getStore()->getRedirectTarget( DIWikiPage::newFromTitle( $source ) )->getDBKey()
+ );
+
+ $this->deletePoolOfPages = [
+ 'DeepRedirectTargetResolverToFindTarget',
+ 'DeepRedirectTargetResolverToFindTarget/1',
+ 'DeepRedirectTargetResolverToFindTarget/2',
+ 'DeepRedirectTargetResolverToFindTarget/3'
+ ];
+ }
+
+ public function testDeepRedirectTargetResolverToDetectCircularTarget() {
+
+ $this->skipTestForMediaWikiVersionLowerThan(
+ '1.20',
+ "Skipping test because circular target (RuntimeException) isn't found on 1.19"
+ );
+
+ $source = Title::newFromText( 'DeepRedirectTargetResolverToDetectCircularTarget' );
+
+ $this->pageCreator
+ ->createPage( $source )
+ ->doEdit( '#REDIRECT [[DeepRedirectTargetResolverToDetectCircularTarget/1]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'DeepRedirectTargetResolverToDetectCircularTarget/1' ) )
+ ->doEdit( '#REDIRECT [[DeepRedirectTargetResolverToDetectCircularTarget/2]]' );
+
+ // Create circular redirect
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'DeepRedirectTargetResolverToDetectCircularTarget/2' ) )
+ ->doEdit( '#REDIRECT [[DeepRedirectTargetResolverToDetectCircularTarget/1]]' );
+
+ $deepRedirectTargetResolver = ApplicationFactory::getInstance()
+ ->newMwCollaboratorFactory()
+ ->newDeepRedirectTargetResolver();
+
+ // Store will point towards the correct target
+ $expectedRedirect = DIWikiPage::newFromTitle(
+ Title::newFromText( 'DeepRedirectTargetResolverToDetectCircularTarget/1' )
+ );
+
+ $this->assertEquals(
+ $expectedRedirect->getDBKey(),
+ $this->getStore()->getRedirectTarget( DIWikiPage::newFromTitle( $source ) )->getDBKey()
+ );
+
+ // Resolver will raise an exception as actions can not act on
+ // a circular redirect oppose to a possible annotation created by the
+ // store
+ $this->setExpectedException( 'RuntimeException' );
+ $deepRedirectTargetResolver->findRedirectTargetFor( $source );
+
+ $this->deletePoolOfPages = [
+ 'DeepRedirectTargetResolverToDetectCircularTarget',
+ 'DeepRedirectTargetResolverToDetectCircularTarget/1',
+ 'DeepRedirectTargetResolverToDetectCircularTarget/2'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/SearchInPageDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/SearchInPageDBIntegrationTest.php
new file mode 100644
index 00000000..3ec632b8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/MediaWiki/SearchInPageDBIntegrationTest.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace SMW\Tests\Integration\MediaWiki;
+
+use SMW\MediaWiki\Search\Search;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Tests\Utils\PageDeleter;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-database
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SearchInPageDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ public function testSearchForPageValueAsTerm() {
+
+ $propertyPage = Title::newFromText( 'Has some page value', SMW_NS_PROPERTY );
+ $targetPage = Title::newFromText( __METHOD__ );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $propertyPage )
+ ->doEdit( '[[Has type::Page]]' );
+
+ $pageCreator
+ ->createPage( $targetPage )
+ ->doEdit( '[[Has some page value::Foo]]' );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $search = new Search();
+ $results = $search->searchText( '[[Has some page value::Foo]]' );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Search\SearchResultSet',
+ $results
+ );
+
+ $this->assertEquals(
+ 1,
+ $results->getTotalHits()
+ );
+
+ $pageDeleter = new PageDeleter();
+ $pageDeleter->deletePage( $targetPage );
+ $pageDeleter->deletePage( $propertyPage );
+ }
+
+ public function testSearchForGeographicCoordinateValueAsTerm() {
+
+ if ( !defined( 'SM_VERSION' ) ) {
+ $this->markTestSkipped( "Requires 'Geographic coordinate' to be a supported data type (see Semantic Maps)" );
+ }
+
+ $propertyPage = Title::newFromText( 'Has coordinates', SMW_NS_PROPERTY );
+ $targetPage = Title::newFromText( __METHOD__ );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $propertyPage )
+ ->doEdit( '[[Has type::Geographic coordinate]]' );
+
+ $pageCreator
+ ->createPage( $targetPage )
+ ->doEdit( "[[Has coordinates::52°31'N, 13°24'E]]" );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $search = new Search();
+ $results = $search->searchText( "[[Has coordinates::52°31'N, 13°24'E]]" );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Search\SearchResultSet',
+ $results
+ );
+
+ if ( is_a( $this->getStore(), '\SMW\SPARQLStore\SPARQLStore' ) ) {
+ $this->markTestIncomplete( "Test was marked as incomplete because the SPARQLStore doesn't support the Geo data type" );
+ }
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->assertEquals(
+ 1,
+ $results->getTotalHits()
+ );
+
+ $pageDeleter = new PageDeleter();
+ $pageDeleter->deletePage( $targetPage );
+ $pageDeleter->deletePage( $propertyPage );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Parser/InTextAnnotationParserTemplateTransclusionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Parser/InTextAnnotationParserTemplateTransclusionTest.php
new file mode 100644
index 00000000..f234f7f8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Parser/InTextAnnotationParserTemplateTransclusionTest.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace SMW\Tests\Integration\Parser;
+
+use ParserOutput;
+use SMW\ApplicationFactory;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class InTextAnnotationParserTemplateTransclusionTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $testEnvironment;
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * Helper method for processing a template transclusion by simulating template
+ * expensions using a callback to avoid having to integrate DB read/write
+ * process in order to access a Template
+ *
+ * @note Part of the routine has been taken from MW's ExtraParserTest
+ *
+ * @return text
+ */
+ private function runTemplateTransclusion( Title $title, $text, $return ) {
+
+ $parser = new \Parser;
+ $options = new \ParserOptions;
+ $options->setTemplateCallback( function ( $title, $parser = false ) use ( $return ) {
+
+ $text = $return;
+ $deps = [];
+
+ return [
+ 'text' => $text,
+ 'finalTitle' => $title,
+ 'deps' => $deps
+ ];
+
+ } );
+
+ return $parser->preprocess( $text, $title, $options );
+ }
+
+ /**
+ * @dataProvider templateDataProvider
+ */
+ public function testPreprocessTemplateAndParse( $namespace, array $settings, $text, $tmplValue, array $expected ) {
+
+ $parserOutput = new ParserOutput();
+ $title = Title::newFromText( __METHOD__, $namespace );
+
+ $outputText = $this->runTemplateTransclusion( $title, $text, $tmplValue );
+
+ $this->testEnvironment->withConfiguration( $settings );
+
+ $parserData = $this->applicationFactory->newParserData(
+ $title,
+ $parserOutput
+ );
+
+ $instance = $this->applicationFactory->newInTextAnnotationParser(
+ $parserData
+ );
+
+ $instance->parse( $outputText );
+
+ $this->assertContains(
+ $expected['resultText'],
+ $outputText
+ );
+
+ $parserData = $this->applicationFactory->newParserData(
+ $title,
+ $parserOutput
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $parserData->getSemanticData()
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function templateDataProvider() {
+
+ $provider = [];
+
+ // #0 Bug 54967
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgLinksInValues' => false,
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ 'smwgMainCacheType' => 'hash'
+ ],
+ '[[Foo::{{Bam}}]]',
+ '?bar',
+ [
+ 'resultText' => '[[:?bar|?bar]]',
+ 'propertyCount' => 1,
+ 'propertyLabels' => [ 'Foo' ],
+ 'propertyValues' => [ '?bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/PropertyLabelCanonicalMatchTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/PropertyLabelCanonicalMatchTest.php
new file mode 100644
index 00000000..fd310800
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/PropertyLabelCanonicalMatchTest.php
@@ -0,0 +1,165 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\DIProperty;
+use SMW\PropertyRegistry;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyLabelCanonicalMatchTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider canonicalLabelProvider
+ */
+ public function testFindPropertyIdByLabel( $label, $expectedKey, $expectedLabel ) {
+
+ list( $labelMatch, $property ) = $this->findPropertyIdByLabel( $label );
+
+ $this->assertEquals(
+ $labelMatch,
+ $expectedLabel
+ );
+
+ $this->assertEquals(
+ $expectedKey,
+ $property->getKey()
+ );
+ }
+
+ /**
+ * @dataProvider canonicalLabelProvider
+ */
+ public function testNewFromUserLabel( $label, $expectedKey, $expectedLabel ) {
+
+ list( $labelMatch, $property ) = $this->newFromUserLabel( $label );
+
+ $this->assertEquals(
+ $labelMatch,
+ $expectedLabel
+ );
+
+ $this->assertEquals(
+ $expectedKey,
+ $property->getKey()
+ );
+ }
+
+ /**
+ * @dataProvider canonicalLabelWithLanguageProvider
+ */
+ public function testNewFromUserLabelWithLanguage( $label, $languageCode, $expectedKey, $expectedLabel ) {
+
+ list( $labelMatch, $property ) = $this->newFromUserLabel( $label, $languageCode );
+
+ $this->assertEquals(
+ $labelMatch,
+ $expectedLabel
+ );
+
+ $this->assertEquals(
+ $expectedKey,
+ $property->getKey()
+ );
+ }
+
+ private function findPropertyIdByLabel( $label ) {
+
+ $property = new DIProperty(
+ PropertyRegistry::getInstance()->findPropertyIdByLabel( $label )
+ );
+
+ $canonicalLabel = $property->getCanonicalLabel();
+
+ // #1966 and #1968
+ // In case something goes wrong, a recursive loop will kill PHP
+ // and we know we messed up
+ if ( $canonicalLabel !== '' && $label !== $canonicalLabel ) {
+ $this->findPropertyIdByLabel(
+ $property->getCanonicalDiWikiPage()->getTitle()->getText()
+ );
+ }
+
+ return [ $label, $property ];
+ }
+
+ private function newFromUserLabel( $label, $languageCode = false ) {
+
+ $property = DIProperty::newFromUserLabel( $label, false, $languageCode );
+
+ $canonicalLabel = $property->getCanonicalLabel();
+
+ // #1966 and #1968
+ // In case something goes wrong, a recursive loop will kill PHP
+ // and we know we messed up
+ if ( $canonicalLabel !== '' && $label !== $canonicalLabel ) {
+ $this->newFromUserLabel(
+ $property->getCanonicalDiWikiPage()->getTitle()->getText()
+ );
+ }
+
+ return [ $label, $property ];
+ }
+
+ public function canonicalLabelProvider() {
+
+ $provider[] = [
+ 'Number',
+ '_num',
+ 'Number',
+ ];
+
+ $provider[] = [
+ 'Float',
+ '_num',
+ 'Float'
+ ];
+
+ $provider[] = [
+ 'Telephone number',
+ '_tel',
+ 'Telephone number'
+ ];
+
+ $provider[] = [
+ 'Phone number',
+ '_tel',
+ 'Phone number'
+ ];
+
+ return $provider;
+ }
+
+ public function canonicalLabelWithLanguageProvider() {
+
+ $provider[] = [
+ 'Number',
+ 'en',
+ '_num',
+ 'Number'
+ ];
+
+ $provider[] = [
+ 'Number',
+ 'fr',
+ '_num',
+ 'Number'
+ ];
+
+ $provider[] = [
+ 'Booléen',
+ 'fr',
+ '_boo',
+ 'Booléen'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/CategoryClassQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/CategoryClassQueryDBIntegrationTest.php
new file mode 100644
index 00000000..1591ec0c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/CategoryClassQueryDBIntegrationTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWPropertyValue as PropertyValue;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class CategoryClassQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $semanticDataFactory;
+
+ private $dataValueFactory;
+ private $queryResultValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ }
+
+ protected function tearDown() {
+
+ foreach ( $this->subjectsToBeCleared as $subject ) {
+ $this->getStore()->deleteSubject( $subject->getTitle() );
+ }
+
+ parent::tearDown();
+ }
+
+ public function testSubjects_onCategoryCondition() {
+
+ $property = new DIProperty( '_INST' );
+
+ $dataValue = $this->dataValueFactory->newDataValueByProperty( $property, 'SomeCategory' );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $semanticData->addDataValue( $dataValue );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->assertArrayHasKey(
+ $property->getKey(),
+ $this->getStore()->getSemanticData( $semanticData->getSubject() )->getProperties()
+ );
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $property );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $semanticData->getSubject(),
+ $this->searchForResultsThatCompareEqualToClassOf( 'SomeCategory' )
+ );
+
+ $this->queryResultValidator->assertThatQueryResultContains(
+ $dataValue,
+ $this->searchForResultsThatCompareEqualToClassOf( 'SomeCategory' )
+ );
+ }
+
+ private function searchForResultsThatCompareEqualToClassOf( $categoryName ) {
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( new DIProperty( '_INST' ) );
+
+ $description = new ClassDescription(
+ new DIWikiPage( $categoryName, NS_CATEGORY, '' )
+ );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ return $this->getStore()->getQueryResult( $query );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ComparatorFilterConditionQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ComparatorFilterConditionQueryDBIntegrationTest.php
new file mode 100644
index 00000000..88b4fcd6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ComparatorFilterConditionQueryDBIntegrationTest.php
@@ -0,0 +1,335 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\DIProperty;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ValueDescription;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMwConjunction as Conjunction;
+use SMWDIBlob as DIBlob;
+use SMWDINumber as DINumber;
+use SMWDITime as DITime;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ComparatorFilterConditionQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $semanticDataFactory;
+ private $queryResultValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ }
+
+ protected function tearDown() {
+
+ foreach ( $this->subjectsToBeCleared as $subject ) {
+ $this->getStore()->deleteSubject( $subject->getTitle() );
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider numericConjunctionFilterProvider
+ */
+ public function testNumericConjunctionConstraints( $range, $parameters, $expected ) {
+ $this->queryPagesThatUseConjunctionConstraintsForPropertyValues( $range, $parameters, $expected );
+ }
+
+ /**
+ * @dataProvider textConjunctionFilterProvider
+ */
+ public function testTextConjunctionConstraints( $range, $parameters, $expected ) {
+ $this->queryPagesThatUseConjunctionConstraintsForPropertyValues( $range, $parameters, $expected );
+ }
+
+ /**
+ * @dataProvider dateConjunctionFilterProvider
+ */
+ public function testDateConjunctionConstraints( $range, $parameters, $expected ) {
+
+ if ( is_a( $this->getStore(), '\SMW\SPARQLStore\SPARQLStore' )
+ && is_a( $this->getStore()->getConnection( 'sparql' ), '\SMW\SPARQLStore\RepositoryConnectors\VirtuosoRepositoryConnector' ) ) {
+ $this->markTestSkipped( "Date filter constraints do not work properly in Virtuoso" );
+ }
+
+ $this->queryPagesThatUseConjunctionConstraintsForPropertyValues( $range, $parameters, $expected );
+ }
+
+ public function queryPagesThatUseConjunctionConstraintsForPropertyValues( $range, $parameters, $expected ) {
+
+ $expectedSubjects = [];
+ $property = $parameters['property'];
+
+ foreach ( $range as $key => $value ) {
+
+ $semanticData = $this->semanticDataFactory
+ ->newEmptySemanticData( __METHOD__ . strval( $key ) );
+
+ $semanticData->addPropertyObjectValue( $property, $value );
+
+ $this->subjectsToBeCleared[] = $semanticData->getSubject();
+ $this->getStore()->updateData( $semanticData );
+
+ if ( in_array( $key, $expected['subjects'] ) ) {
+ $expectedSubjects[] = $semanticData->getSubject();
+ }
+ }
+
+ $description = new Conjunction( [
+ new SomeProperty(
+ $property,
+ new ValueDescription( $parameters['lower'], null, $parameters['lowerComp'] ) ),
+ new SomeProperty(
+ $property,
+ new ValueDescription( $parameters['upper'], null, $parameters['upperComp'] ) ),
+ ] );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->assertEquals(
+ $expected['count'],
+ $queryResult->getCount()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $expectedSubjects,
+ $queryResult
+ );
+ }
+
+ public function numericConjunctionFilterProvider() {
+
+ $property = new DIProperty( 'SomeNumericPropertyToFilter' );
+ $property->setPropertyTypeId( '_num' );
+
+ #0 Numeric Greater Equal, Less Equal
+ $provider[] = [
+ [
+ 1 => new DINumber( 1 ),
+ 6 => new DINumber( 6 ),
+ 10 => new DINumber( 10 )
+ ],
+ [
+ 'lower' => new DINumber( 1 ),
+ 'upper' => new DINumber( 9 ),
+ 'lowerComp' => SMW_CMP_GEQ,
+ 'upperComp' => SMW_CMP_LEQ,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 2,
+ 'subjects' => [ 1, 6 ]
+ ]
+ ];
+
+ #1 Numeric Greater, Equal
+ $provider[] = [
+ [
+ 1 => new DINumber( 1 ),
+ 2 => new DINumber( 2 ),
+ 6 => new DINumber( 6 ),
+ 10 => new DINumber( 10 )
+ ],
+ [
+ 'lower' => new DINumber( 1 ),
+ 'upper' => new DINumber( 10 ),
+ 'lowerComp' => SMW_CMP_GRTR,
+ 'upperComp' => SMW_CMP_LESS,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 2,
+ 'subjects' => [ 2, 6 ]
+ ]
+ ];
+
+ #2 Numeric Greater, Less
+ $provider[] = [
+ [
+ 1 => new DINumber( 1 ),
+ 2 => new DINumber( 2 )
+ ],
+ [
+ 'lower' => new DINumber( 1 ),
+ 'upper' => new DINumber( 2 ),
+ 'lowerComp' => SMW_CMP_GRTR,
+ 'upperComp' => SMW_CMP_LESS,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 0,
+ 'subjects' => []
+ ]
+ ];
+
+ #3 Numeric Greater, Not Like
+ $provider[] = [
+ [
+ 1 => new DINumber( 1 ),
+ 2 => new DINumber( 2 ),
+ 3 => new DINumber( 3 )
+ ],
+ [
+ 'lower' => new DINumber( 1 ),
+ 'upper' => new DINumber( 3 ),
+ 'lowerComp' => SMW_CMP_GRTR,
+ 'upperComp' => SMW_CMP_NEQ,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 1,
+ 'subjects' => [ 2 ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function textConjunctionFilterProvider() {
+
+ $property = new DIProperty( 'SomeBlobPropertyToFilter' );
+ $property->setPropertyTypeId( '_txt' );
+
+ #4 Text, Greater Equal, Less Equal
+ $provider[] = [
+ [
+ 'AA' => new DIBlob( 'AA' ),
+ 'BB' => new DIBlob( 'BB' ),
+ 'CC' => new DIBlob( 'CC' )
+ ],
+ [
+ 'lower' => new DIBlob( 'AA' ),
+ 'upper' => new DIBlob( 'BB' ),
+ 'lowerComp' => SMW_CMP_GEQ,
+ 'upperComp' => SMW_CMP_LEQ,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 2,
+ 'subjects' => [ 'AA', 'BB' ]
+ ]
+ ];
+
+ #5 Text, Like, Like
+ $provider[] = [
+ [
+ 'A' => new DIBlob( 'A' ),
+ 'AA' => new DIBlob( 'AA' ),
+ 'BBA' => new DIBlob( 'BBA' ),
+ 'AAC' => new DIBlob( 'AAC' )
+ ],
+ [
+ 'lower' => new DIBlob( 'A*' ),
+ 'upper' => new DIBlob( 'AA*' ),
+ 'lowerComp' => SMW_CMP_LIKE,
+ 'upperComp' => SMW_CMP_LIKE,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 2,
+ 'subjects' => [ 'AA', 'AAC' ]
+ ]
+ ];
+
+ #6 Text, Like, Not Like
+ $provider[] = [
+ [
+ 'AABA' => new DIBlob( 'AABA' ),
+ 'AACA' => new DIBlob( 'AACA' ),
+ 'AAAB' => new DIBlob( 'AAAB' ),
+ ],
+ [
+ 'lower' => new DIBlob( 'AA?A' ),
+ 'upper' => new DIBlob( 'AA?B' ),
+ 'lowerComp' => SMW_CMP_LIKE,
+ 'upperComp' => SMW_CMP_NLKE,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 2,
+ 'subjects' => [ 'AABA', 'AACA' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function dateConjunctionFilterProvider() {
+
+ $property = new DIProperty( 'SomeDatePropertyToFilter' );
+ $property->setPropertyTypeId( '_dat' );
+
+ #7 Date, Greater Equal, Less Equal
+ $provider[] = [
+ [
+ '197001' => new DITime( 1, 1970, 01, 01, 1, 1 ),
+ '197002' => new DITime( 1, 1970, 02, 01, 1, 1 ),
+ '197003' => new DITime( 1, 1970, 03, 01, 1, 1 ),
+ ],
+ [
+ 'lower' => new DITime( 1, 1970, 01, 01 ),
+ 'upper' => new DITime( 1, 1970, 03, 01 ),
+ 'lowerComp' => SMW_CMP_GEQ,
+ 'upperComp' => SMW_CMP_LEQ,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 2,
+ 'subjects' => [ '197001', '197002' ]
+ ]
+ ];
+
+ #7 Date, Greater Equal, Less Equal
+ $provider[] = [
+ [
+ '1970011' => new DITime( 1, 1970, 01, 01, 1, 1 ),
+ '1970012' => new DITime( 1, 1970, 01, 02, 1, 1 ),
+ '1970013' => new DITime( 1, 1970, 01, 03, 1, 1 ),
+ ],
+ [
+ 'lower' => new DITime( 1, 1970, 01, 01, 2 ),
+ 'upper' => new DITime( 1, 1970, 01, 02, 2 ),
+ 'lowerComp' => SMW_CMP_GRTR,
+ 'upperComp' => SMW_CMP_LESS,
+ 'property' => $property,
+ ],
+ [
+ 'count' => 1,
+ 'subjects' => [ '1970012' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ConjunctionQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ConjunctionQueryDBIntegrationTest.php
new file mode 100644
index 00000000..c20548cd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ConjunctionQueryDBIntegrationTest.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ValueDescription;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ConjunctionQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $semanticDataFactory;
+ private $queryResultValidator;
+ private $queryParser;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = UtilityFactory::getInstance();
+
+ $this->semanticDataFactory = $utilityFactory->newSemanticDataFactory();
+ $this->queryResultValidator = $utilityFactory->newValidatorFactory()->newQueryResultValidator();
+
+ $this->fixturesProvider = $utilityFactory->newFixturesFactory()->newFixturesProvider();
+ $this->fixturesProvider->setupDependencies( $this->getStore() );
+
+ $this->queryParser = ApplicationFactory::getInstance()->getQueryFactory()->newQueryParser();
+ }
+
+ protected function tearDown() {
+
+ $fixturesCleaner = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesCleaner();
+ $fixturesCleaner
+ ->purgeSubjects( $this->subjectsToBeCleared )
+ ->purgeAllKnownFacts();
+
+ parent::tearDown();
+ }
+
+ /**
+ * {{#ask: [[Category:HappyPlaces]] [[LocatedIn.MemberOf::Wonderland]] }}
+ */
+ public function testConjunctionForCategoryAndPropertyChainSubqueryThatComparesEqualToSpecifiedValue() {
+
+ /**
+ * Page ...-neverland annotated with [[LocatedIn::BananaWonderland]]
+ */
+ $semanticDataOfNeverland = $this->semanticDataFactory
+ ->setTitle( __METHOD__ . '-neverland' )
+ ->newEmptySemanticData();
+
+ $semanticDataOfNeverland->addPropertyObjectValue(
+ DIProperty::newFromUserLabel( 'LocatedIn' )->setPropertyTypeId( '_wpg' ),
+ new DIWikiPage( 'BananaWonderland', NS_MAIN )
+ );
+
+ $this->getStore()->updateData( $semanticDataOfNeverland );
+
+ /**
+ * Page ...-dreamland annotated with [[Category:HappyPlaces]] [[LocatedIn::BananaWonderland]]
+ */
+ $semanticDataOfDreamland = $this->semanticDataFactory
+ ->setTitle( __METHOD__ . '-dreamland' )
+ ->newEmptySemanticData();
+
+ $semanticDataOfDreamland->addPropertyObjectValue(
+ DIProperty::newFromUserLabel( 'LocatedIn' )->setPropertyTypeId( '_wpg' ),
+ new DIWikiPage( 'BananaWonderland', NS_MAIN )
+ );
+
+ $semanticDataOfDreamland->addPropertyObjectValue(
+ new DIProperty( '_INST' ),
+ new DIWikiPage( 'HappyPlaces', NS_CATEGORY )
+ );
+
+ $this->getStore()->updateData( $semanticDataOfDreamland );
+
+ /**
+ * Page BananaWonderland annotated with [[MemberOf::Wonderland]]
+ */
+ $semanticDataOfWonderland = $this->semanticDataFactory
+ ->setTitle( 'BananaWonderland' )
+ ->newEmptySemanticData();
+
+ $semanticDataOfWonderland->addPropertyObjectValue(
+ DIProperty::newFromUserLabel( 'MemberOf' )->setPropertyTypeId( '_wpg' ),
+ new DIWikiPage( 'Wonderland', NS_MAIN )
+ );
+
+ $this->getStore()->updateData( $semanticDataOfWonderland );
+
+ $someProperty = new SomeProperty(
+ DIProperty::newFromUserLabel( 'LocatedIn' )->setPropertyTypeId( '_wpg' ),
+ new SomeProperty(
+ DIProperty::newFromUserLabel( 'MemberOf' )->setPropertyTypeId( '_wpg' ),
+ new ValueDescription(
+ new DIWikiPage( 'Wonderland', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'MemberOf' )->setPropertyTypeId( '_wpg' ), SMW_CMP_EQ
+ )
+ )
+ );
+
+ $classDescription = new ClassDescription(
+ new DIWikiPage( 'HappyPlaces', NS_CATEGORY, '' )
+ );
+
+ $description = new Conjunction();
+ $description->addDescription( $classDescription );
+ $description->addDescription( $someProperty );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:HappyPlaces]] [[LocatedIn.MemberOf::Wonderland]]' )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:HappyPlaces]] [[LocatedIn::<q>[[MemberOf::Wonderland]]</q>]]' )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $expectedSubjects = [
+ $semanticDataOfDreamland->getSubject()
+ ];
+
+ $this->assertEquals(
+ 1,
+ $queryResult->getCount()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $expectedSubjects,
+ $queryResult
+ );
+
+ $this->subjectsToBeCleared = [
+ $semanticDataOfWonderland->getSubject(),
+ $semanticDataOfDreamland->getSubject(),
+ $semanticDataOfNeverland->getSubject()
+ ];
+ }
+
+ public function testNestedPropertyConjunction() {
+
+ /**
+ * Page annotated with [[Born in::Paris]]
+ */
+ $property = DIProperty::newFromUserLabel( 'Born in' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ . 'PageOughtToBeSelected' );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( 'Paris', NS_MAIN )
+ );
+
+ $expectedSubjects = $semanticData->getSubject();
+ $this->subjectsToBeCleared[] = $semanticData->getSubject();
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->getStore()->updateData(
+ $this->fixturesProvider->getFactsheet( 'Paris' )->asEntity()
+ );
+
+ /**
+ * @query [[Born in::<q>[[Category:City]] [[Located in::France]]</q>]]
+ */
+ $cityCategory = $this->fixturesProvider->getCategory( 'city' )->asSubject();
+ $locatedInProperty = $this->fixturesProvider->getProperty( 'locatedin' );
+
+ $conjunction = new Conjunction( [
+ new ClassDescription( $cityCategory ),
+ new SomeProperty(
+ $locatedInProperty,
+ new ValueDescription(
+ $this->fixturesProvider->getFactsheet( 'France' )->asSubject(),
+ $locatedInProperty )
+ )
+ ]
+ );
+
+ $description = new SomeProperty(
+ $property,
+ $conjunction
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Born in::<q>[[Category:City]] [[Located in::France]]</q>]]' )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->assertEquals(
+ 1,
+ $queryResult->getCount()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $expectedSubjects,
+ $queryResult
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DatePropertyValueQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DatePropertyValueQueryDBIntegrationTest.php
new file mode 100644
index 00000000..d797141c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DatePropertyValueQueryDBIntegrationTest.php
@@ -0,0 +1,173 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWExporter as Exporter;
+use SMWPropertyValue as PropertyValue;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class DatePropertyValueQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $semanticDataFactory;
+ private $dataValueFactory;
+ private $queryResultValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+
+ $this->fixturesProvider = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesProvider();
+ $this->fixturesProvider->setupDependencies( $this->getStore() );
+ }
+
+ protected function tearDown() {
+
+ $fixturesCleaner = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesCleaner();
+
+ $fixturesCleaner
+ ->purgeAllKnownFacts()
+ ->purgeSubjects( $this->subjectsToBeCleared );
+
+ parent::tearDown();
+ }
+
+ public function testUserDefinedDateProperty() {
+
+ $property = new DIProperty( 'SomeDateProperty' );
+ $property->setPropertyTypeId( '_dat' );
+
+ $dataValue = $this->dataValueFactory->newDataValueByProperty(
+ $property,
+ '1 January 1970'
+ );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $semanticData->addDataValue( $dataValue );
+
+ $this->getStore()->updateData( $semanticData );
+
+ Exporter::getInstance()->clear();
+
+ $this->assertArrayHasKey(
+ $property->getKey(),
+ $this->getStore()->getSemanticData( $semanticData->getSubject() )->getProperties()
+ );
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $property );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->queryResultValidator->assertThatQueryResultContains(
+ $dataValue,
+ $queryResult
+ );
+
+ $this->subjectsToBeCleared[] = $semanticData->getSubject();
+ }
+
+ /**
+ * #576
+ */
+ public function testSortableDateQuery() {
+
+ $this->getStore()->updateData(
+ $this->fixturesProvider->getFactsheet( 'Berlin' )->asEntity()
+ );
+
+ // #576 introduced resource caching, therefore make sure that the
+ // instance is cleared after data have been created before further
+ // tests are carried out
+ Exporter::getInstance()->clear();
+
+ /**
+ * @query {{#ask: [[Founded::SomeDistinctValue]] }}
+ */
+ $foundedValue = $this->fixturesProvider->getFactsheet( 'Berlin' )->getFoundedValue();
+
+ $description = new SomeProperty(
+ $foundedValue->getProperty(),
+ new ValueDescription( $foundedValue->getDataItem(), null, SMW_CMP_EQ )
+ );
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $foundedValue->getProperty() );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $query->sortkeys = [
+ $foundedValue->getProperty()->getLabel() => 'ASC'
+ ];
+
+ // Be aware of
+ // Virtuoso 22023 Error SR353: Sorted TOP clause specifies more then
+ // 10001 rows to sort. Only 10000 are allowed. Either decrease the
+ // offset and/or row count or use a scrollable cursor
+ $query->setLimit( 100 );
+
+ $query->setExtraPrintouts( [
+ new PrintRequest( PrintRequest::PRINT_THIS, '' ),
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ ] );
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $this->fixturesProvider->getFactsheet( 'Berlin' )->asSubject(),
+ $queryResult
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DisjunctionQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DisjunctionQueryDBIntegrationTest.php
new file mode 100644
index 00000000..8623baf3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/DisjunctionQueryDBIntegrationTest.php
@@ -0,0 +1,238 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ValueDescription;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWQuery as Query;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class DisjunctionQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $semanticDataFactory;
+ private $queryResultValidator;
+ private $queryParser;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->queryParser = ApplicationFactory::getInstance()->getQueryFactory()->newQueryParser();
+
+ // $this->getStore()->getSparqlDatabase()->deleteAll();
+ }
+
+ protected function tearDown() {
+
+ foreach ( $this->subjectsToBeCleared as $subject ) {
+ $this->getStore()->deleteSubject( $subject->getTitle() );
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * {{#ask: [[Category:WickedPlaces]] OR [[LocatedIn.MemberOf::Wonderland]] }}
+ */
+ public function testDisjunctionSubqueryForPageTypePropertyChainThatComparesEqualToValue() {
+
+ /**
+ * Page ...-dangerland annotated with [[Category:WickedPlaces]]
+ */
+ $semanticDataOfDangerland = $this->semanticDataFactory
+ ->setTitle( __METHOD__ . '-dangerland' )
+ ->newEmptySemanticData();
+
+ $semanticDataOfDangerland->addPropertyObjectValue(
+ new DIProperty( '_INST' ),
+ new DIWikiPage( 'WickedPlaces', NS_CATEGORY )
+ );
+
+ $this->subjectsToBeCleared[] = $semanticDataOfDangerland->getSubject();
+ $this->getStore()->updateData( $semanticDataOfDangerland );
+
+ /**
+ * Page ...-dreamland annotated with [[LocatedIn::BananaWonderland]]
+ */
+ $semanticDataOfDreamland = $this->semanticDataFactory
+ ->setTitle( __METHOD__ . '-dreamland' )
+ ->newEmptySemanticData();
+
+ $semanticDataOfDreamland->addPropertyObjectValue(
+ DIProperty::newFromUserLabel( 'LocatedIn' )->setPropertyTypeId( '_wpg' ),
+ new DIWikiPage( 'BananaWonderland', NS_MAIN )
+ );
+
+ $this->subjectsToBeCleared[] = $semanticDataOfDreamland->getSubject();
+ $this->getStore()->updateData( $semanticDataOfDreamland );
+
+ /**
+ * Page BananaWonderland annotated with [[MemberOf::Wonderland]]
+ */
+ $semanticDataOfWonderland = $this->semanticDataFactory
+ ->setTitle( 'BananaWonderland' )
+ ->newEmptySemanticData();
+
+ $semanticDataOfWonderland->addPropertyObjectValue(
+ DIProperty::newFromUserLabel( 'MemberOf' )->setPropertyTypeId( '_wpg' ),
+ new DIWikiPage( 'Wonderland', NS_MAIN )
+ );
+
+ $this->subjectsToBeCleared[] = $semanticDataOfWonderland->getSubject();
+ $this->getStore()->updateData( $semanticDataOfWonderland );
+
+ /**
+ * Query with [[Category:WickedPlaces]] OR [[LocatedIn.MemberOf::Wonderland]]
+ */
+ $someProperty = new SomeProperty(
+ DIProperty::newFromUserLabel( 'LocatedIn' )->setPropertyTypeId( '_wpg' ),
+ new SomeProperty(
+ DIProperty::newFromUserLabel( 'MemberOf' )->setPropertyTypeId( '_wpg' ),
+ new ValueDescription(
+ new DIWikiPage( 'Wonderland', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'MemberOf' )->setPropertyTypeId( '_wpg' ), SMW_CMP_EQ
+ )
+ )
+ );
+
+ $classDescription = new ClassDescription(
+ new DIWikiPage( 'WickedPlaces', NS_CATEGORY, '' )
+ );
+
+ $description = new Disjunction();
+ $description->addDescription( $classDescription );
+ $description->addDescription( $someProperty );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:WickedPlaces]] OR [[LocatedIn.MemberOf::Wonderland]]' )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:WickedPlaces]] OR [[LocatedIn::<q>[[MemberOf::Wonderland]]</q>]]' )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $expectedSubjects = [
+ $semanticDataOfDreamland->getSubject(),
+ $semanticDataOfDangerland->getSubject()
+ ];
+
+ $this->assertEquals(
+ 2,
+ $queryResult->getCount()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $expectedSubjects,
+ $queryResult
+ );
+ }
+
+ public function testSubqueryDisjunction() {
+
+ $property = new DIProperty( 'HasSomeProperty' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ /**
+ * Page annotated with [[HasSomeProperty:Foo]]
+ */
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ . '1' );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $expectedSubjects[] = $semanticData->getSubject();
+ $this->subjectsToBeCleared[] = $semanticData->getSubject();
+
+ $this->getStore()->updateData( $semanticData );
+
+ /**
+ * Page annotated with [[HasSomeProperty:Bar]]
+ */
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ . '2' );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( 'Bar', NS_MAIN )
+ );
+
+ $expectedSubjects[] = $semanticData->getSubject();
+ $this->subjectsToBeCleared[] = $semanticData->getSubject();
+
+ $this->getStore()->updateData( $semanticData );
+
+ /**
+ * Query with [[HasSomeProperty::Foo||Bar]]
+ */
+ $disjunction = new Disjunction( [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ), $property ),
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ), $property )
+ ] );
+
+ $description = new SomeProperty(
+ $property,
+ $disjunction
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[HasSomeProperty::Foo||Bar]]' )
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->assertEquals(
+ 2,
+ $queryResult->getCount()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $expectedSubjects,
+ $queryResult
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/GeneralQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/GeneralQueryDBIntegrationTest.php
new file mode 100644
index 00000000..222207a8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/GeneralQueryDBIntegrationTest.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWPropertyValue as PropertyValue;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class GeneralQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $subject;
+
+ private $dataValueFactory;
+ private $queryResultValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+
+ $this->testEnvironment->addConfiguration( 'smwgQueryResultCacheType', false );
+ }
+
+ protected function tearDown() {
+
+ foreach ( $this->subjectsToBeCleared as $subject ) {
+ $this->getStore()->deleteSubject( $subject->getTitle() );
+ }
+
+ parent::tearDown();
+ }
+
+ public function testPropertyBeforeAfterDataRemoval() {
+
+ $property = new DIProperty( 'SomePagePropertyBeforeAfter' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $this->assertEmpty(
+ $this->searchForResultsThatCompareEqualToOnlySingularPropertyOf( $property )->getResults()
+ );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByItem( $semanticData->getSubject(), $property )
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->queryResultValidator->assertThatQueryResultContains(
+ $semanticData->getSubject(),
+ $this->searchForResultsThatCompareEqualToOnlySingularPropertyOf( $property )
+ );
+
+ $this->assertNotEmpty(
+ $this->searchForResultsThatCompareEqualToOnlySingularPropertyOf( $property )->getResults()
+ );
+
+ $this->getStore()->clearData( $semanticData->getSubject() );
+
+ $this->assertEmpty(
+ $this->searchForResultsThatCompareEqualToOnlySingularPropertyOf( $property )->getResults()
+ );
+
+ $this->subjectsToBeCleared = [
+ $semanticData->getSubject()
+ ];
+ }
+
+ public function testUserDefinedPropertyUsedForInvalidValueAssignment() {
+
+ $property = new DIProperty( 'SomePropertyWithInvalidValueAssignment' );
+ $property->setPropertyTypeId( '_tem' );
+
+ $dataValue = $this->dataValueFactory->newDataValueByProperty( $property, '1 Jan 1970' );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+ $semanticData->addDataValue( $dataValue );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->assertEquals(
+ 0,
+ $this->searchForResultsThatCompareEqualToOnlySingularPropertyOf( $property )->getCount()
+ );
+
+ $this->subjectsToBeCleared = [
+ $semanticData->getSubject()
+ ];
+ }
+
+ private function searchForResultsThatCompareEqualToOnlySingularPropertyOf( DIProperty $property ) {
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $property );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+
+ $query = new Query(
+ $description
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ return $this->getStore()->getQueryResult( $query );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/InversePropertyRelationshipDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/InversePropertyRelationshipDBIntegrationTest.php
new file mode 100644
index 00000000..f45f5f11
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/InversePropertyRelationshipDBIntegrationTest.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ValueDescription;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWQuery as Query;
+
+/**
+ * @see http://semantic-mediawiki.org/wiki/Inverse_Properties
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class InversePropertyRelationshipDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+
+ private $semanticDataFactory;
+ private $dataValueFactory;
+
+ private $queryResultValidator;
+ private $queryParser;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->queryParser = ApplicationFactory::getInstance()->getQueryFactory()->newQueryParser();
+ }
+
+ protected function tearDown() {
+
+ foreach ( $this->subjectsToBeCleared as $subject ) {
+ $this->getStore()->deleteSubject( $subject->getTitle() );
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * {{#ask: [[-Has mother::Michael]] }}
+ */
+ public function testParentChildInverseRelationshipQuery() {
+
+ $semanticData = $this->semanticDataFactory
+ ->setTitle( 'Michael' )
+ ->newEmptySemanticData();
+
+ $semanticData->addDataValue(
+ $this->newDataValueForPagePropertyValue( 'Has mother', 'Carol' )
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $description = new SomeProperty(
+ DIProperty::newFromUserLabel( 'Has mother', true )->setPropertyTypeId( '_wpg' ),
+ new ValueDescription(
+ new DIWikiPage( 'Michael', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'Has mother', true )->setPropertyTypeId( '_wpg' ),
+ SMW_CMP_EQ
+ )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[-Has mother::Michael]]' )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->assertEquals(
+ 1,
+ $queryResult->getCount()
+ );
+
+ $expectedSubjects = [
+ new DIWikiPage( 'Carol', NS_MAIN, '' )
+ ];
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $expectedSubjects,
+ $queryResult
+ );
+
+ $this->subjectsToBeCleared = [
+ $semanticData->getSubject()
+ ];
+ }
+
+ private function newDataValueForPagePropertyValue( $property, $value ) {
+
+ $property = DIProperty::newFromUserLabel( $property );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $dataItem = new DIWikiPage( $value, NS_MAIN, '' );
+
+ return $this->dataValueFactory->newDataValueByItem(
+ $dataItem,
+ $property
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NamespaceQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NamespaceQueryDBIntegrationTest.php
new file mode 100644
index 00000000..122134bd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NamespaceQueryDBIntegrationTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ValueDescription;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class NamespaceQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $fixturesProvider;
+ private $semanticDataFactory;
+
+ private $queryResultValidator;
+ private $subjects = [];
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+
+ $this->fixturesProvider = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesProvider();
+ $this->fixturesProvider->setupDependencies( $this->getStore() );
+ }
+
+ protected function tearDown() {
+
+ $fixturesCleaner = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesCleaner();
+ $fixturesCleaner
+ ->purgeSubjects( $this->subjects )
+ ->purgeAllKnownFacts();
+
+ parent::tearDown();
+ }
+
+ public function testConjunctiveNamespaceQueryThatIncludesSubobject() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+ $this->subjects[] = $semanticData->getSubject();
+
+ $factsheet = $this->fixturesProvider->getFactsheet( 'Berlin' );
+ $factsheet->setTargetSubject( $semanticData->getSubject() );
+
+ $demographicsSubobject = $factsheet->getDemographics();
+ $this->subjects[] = $demographicsSubobject->getSemanticData()->getSubject();
+
+ $semanticData->addPropertyObjectValue(
+ $demographicsSubobject->getProperty(),
+ $demographicsSubobject->getContainer()
+ );
+
+ $populationValue = $factsheet->getPopulationValue();
+ $semanticData->addDataValue( $populationValue );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $someProperty = new SomeProperty(
+ $populationValue->getProperty(),
+ new ValueDescription( $populationValue->getDataItem(), null, SMW_CMP_EQ )
+ );
+
+ /**
+ * @query [[Population::SomeDistinctPopulationValue]][[:+]]
+ */
+ $description = new Conjunction();
+ $description->addDescription( $someProperty );
+ $description->addDescription( new NamespaceDescription( NS_MAIN ) );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->assertEquals(
+ 2,
+ $queryResult->getCount()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $this->subjects,
+ $queryResult
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NullQueryResultTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NullQueryResultTest.php
new file mode 100644
index 00000000..7e977e34
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/NullQueryResultTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\ValueDescription;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class NullQueryResultTest extends \PHPUnit_Framework_TestCase {
+
+ public function testNullQueryResult() {
+
+ $term = '[[Some_string_to_query]]';
+
+ $description = new ValueDescription(
+ new DIWikiPage( $term, NS_MAIN ),
+ null
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $description = $query->getDescription();
+
+ $namespacesDisjunction = new Disjunction(
+ array_map( function ( $ns ) {
+ return new NamespaceDescription( $ns );
+ }, [ NS_MAIN ] )
+ );
+
+ $description = new Conjunction( [ $description, $namespacesDisjunction ] );
+
+ $query->setDescription( $description );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ ApplicationFactory::getInstance()->getStore()->getQueryResult( $query )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ProfileAnnotators/ProfileAnnotatorWithQueryProcessorIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ProfileAnnotators/ProfileAnnotatorWithQueryProcessorIntegrationTest.php
new file mode 100644
index 00000000..6f49266f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/ProfileAnnotators/ProfileAnnotatorWithQueryProcessorIntegrationTest.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace SMW\Tests\Integration\Query\ProfileAnnotators;
+
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Tests\TestEnvironment;
+use SMWQueryProcessor;
+
+/**
+ * @covers \SMWQueryProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ProfileAnnotatorWithQueryProcessorIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testCreateProfile( array $rawParams, array $expected ) {
+
+ list( $query, $formattedParams ) = SMWQueryProcessor::getQueryAndParamsFromFunctionParams(
+ $rawParams,
+ SMW_OUTPUT_WIKI,
+ SMWQueryProcessor::INLINE_QUERY,
+ false
+ );
+
+ $query->setContextPage(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $profileAnnotatorFactory = ApplicationFactory::getInstance()->getQueryFactory()->newProfileAnnotatorFactory();
+
+ $profileAnnotator = $profileAnnotatorFactory->newProfileAnnotator(
+ $query,
+ $formattedParams['format']->getValue()
+ );
+
+ $profileAnnotator->addAnnotation();
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $profileAnnotator->getSemanticData()
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $profileAnnotator->getSemanticData()
+ );
+ }
+
+ public function queryDataProvider() {
+
+ $categoryNS = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+
+ $provider = [];
+
+ // #0
+ // {{#ask: [[Modification date::+]]
+ // |?Modification date
+ // |format=list
+ // }}
+ $provider[] = [
+ [
+ '',
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'list', 1, 1, '[[Modification date::+]]' ]
+ ]
+ ];
+
+ // #1
+ // {{#ask: [[Modification date::+]][[Category:Foo]]
+ // |?Modification date
+ // |?Has title
+ // |format=list
+ // }}
+ $provider[] = [
+ [
+ '',
+ '[[Modification date::+]][[Category:Foo]]',
+ '?Modification date',
+ '?Has title',
+ 'format=list'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'list', 2, 1, "[[Modification date::+]] [[$categoryNS:Foo]]" ]
+ ]
+ ];
+
+ // #2 Unknown format, default table
+ // {{#ask: [[Modification date::+]][[Category:Foo]]
+ // |?Modification date
+ // |?Has title
+ // |format=bar
+ // }}
+ $provider[] = [
+ [
+ '',
+ '[[Modification date::+]][[Category:Foo]]',
+ '?Modification date',
+ '?Has title',
+ 'format=bar'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'table', 2, 1, "[[Modification date::+]] [[$categoryNS:Foo]]" ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QueryResultPrinterIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QueryResultPrinterIntegrationTest.php
new file mode 100644
index 00000000..7d36ff95
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QueryResultPrinterIntegrationTest.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace SMW\Tests\Integration\Query\ResultPrinter;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @group semantic-mediawiki-integration
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class QueryResultPrinterIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjects = [];
+ private $pageCreator;
+
+ private $stringBuilder;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = UtilityFactory::getInstance();
+
+ $this->pageCreator = $utilityFactory->newPageCreator();
+ $this->stringBuilder = $utilityFactory->newStringBuilder();
+ $this->stringValidator = $utilityFactory->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ UtilityFactory::getInstance()->newPageDeleter()->doDeletePoolOfPages( $this->subjects );
+ parent::tearDown();
+ }
+
+ /**
+ * @see #755
+ * @query {{#ask: [[Modification date::+]]|limit=0|searchlabel= }}
+ */
+ public function testLimitNullWithEmptySearchlabel() {
+
+ foreach ( [ 'Foo', 'Bar', 'テスト' ] as $title ) {
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( $title ) )
+ ->doEdit( '[[Category:LimitNullForEmptySearchlabel]]');
+
+ $this->subjects[] = $this->pageCreator->getPage();
+ }
+
+ $this->stringBuilder
+ ->addString( '{{#ask:' )
+ ->addString( '[[Modification date::+]][[Category:LimitNullForEmptySearchlabel]]' )
+ ->addString( '|limit=0' )
+ ->addString( '|searchlabel=' )
+ ->addString( '}}' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( __METHOD__ ) )
+ ->doEdit( $this->stringBuilder->getString() );
+
+ $this->subjects[] = $this->pageCreator->getPage();
+
+ $parserOutput = $this->pageCreator->getEditInfo()->output;
+
+ $this->assertNotContains(
+ '[[Special:Ask/-5B-5BModification-20date::+-5D-5D-5B-5BCategory:LimitNullForEmptySearchlabel-5D-5D/searchlabel=/offset=0|]]',
+ $parserOutput->getText()
+ );
+ }
+
+ /**
+ * @see #755
+ * @query {{#ask: [[Modification date::+]]|limit=0|searchlabel=do something }}
+ */
+ public function testLimitNullWithDescriptiveSearchlabel() {
+
+ foreach ( [ 'Foo', 'Bar', 'テスト' ] as $title ) {
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( $title ) )
+ ->doEdit( '[[Category:LimitNullForNotEmptySearchlabel]]');
+
+ $this->subjects[] = $this->pageCreator->getPage();
+ }
+
+ $this->stringBuilder
+ ->addString( '{{#ask:' )
+ ->addString( '[[Modification date::+]][[Category:LimitNullForNotEmptySearchlabel]]' )
+ ->addString( '|limit=0' )
+ ->addString( '|searchlabel=do something' )
+ ->addString( '}}' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( __METHOD__ ) )
+ ->doEdit( $this->stringBuilder->getString() );
+
+ $this->subjects[] = $this->pageCreator->getPage();
+
+ $parserOutput = $this->pageCreator->getEditInfo()->output;
+
+ $this->assertContains(
+ 'do something',
+ $parserOutput->getText()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QuerySourceIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QuerySourceIntegrationTest.php
new file mode 100644
index 00000000..2b99583b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/QuerySourceIntegrationTest.php
@@ -0,0 +1,192 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+use SMWQueryProcessor;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class QuerySourceIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $testEnvironment;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgQuerySources',
+ [
+ 'foo' => 'SMW\Tests\Utils\Mock\FakeQueryStore',
+ 'foobar' => 'SMW\Tests\Integration\Query\AnotherFakeQueryStoreWhichDoesNotImplentTheQueryEngineInterface',
+ 'bar' => 'SMW\Tests\NonExistentQueryStore',
+ ]
+ );
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testQueryProcessorWithDefaultSource() {
+
+ $queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $rawParams = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list',
+ 'source=default'
+ ];
+
+ $this->assertInternalType(
+ 'string',
+ $this->makeQueryResultFromRawParameters( $rawParams )
+ );
+ }
+
+ public function testQueryProcessorWithValidSource() {
+
+ $queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $rawParams = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list',
+ 'source=foo'
+ ];
+
+ $this->assertInternalType(
+ 'string',
+ $this->makeQueryResultFromRawParameters( $rawParams )
+ );
+ }
+
+ public function testQueryProcessorWithInvalidSourceSwitchesToDefault() {
+
+ $queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $rawParams = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list',
+ 'source=bar'
+ ];
+
+ $this->assertInternalType(
+ 'string',
+ $this->makeQueryResultFromRawParameters( $rawParams )
+ );
+ }
+
+ public function testQuerySourceOnCount() {
+
+ $queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getCountValue' )
+ ->will( $this->returnValue( 42 ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $rawParams = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=count',
+ 'source=foo'
+ ];
+
+ $this->assertInternalType(
+ 'string',
+ $this->makeQueryResultFromRawParameters( $rawParams )
+ );
+ }
+
+ public function testQueryProcessorWithInvalidSource() {
+
+ $rawParams = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list',
+ 'source=foobar'
+ ];
+
+ $this->setExpectedException( 'RuntimeException' );
+ $this->makeQueryResultFromRawParameters( $rawParams );
+ }
+
+ protected function makeQueryResultFromRawParameters( $rawParams ) {
+
+ list( $query, $params ) = SMWQueryProcessor::getQueryAndParamsFromFunctionParams(
+ $rawParams,
+ SMW_OUTPUT_WIKI,
+ SMWQueryProcessor::INLINE_QUERY,
+ false
+ );
+
+ return SMWQueryProcessor::getResultFromQuery(
+ $query,
+ $params,
+ SMW_OUTPUT_WIKI,
+ SMWQueryProcessor::INLINE_QUERY
+ );
+ }
+
+}
+
+class AnotherFakeQueryStoreWhichDoesNotImplentTheQueryEngineInterface {
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/RandomQueryResultOrderIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/RandomQueryResultOrderIntegrationTest.php
new file mode 100644
index 00000000..aeee31c4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/RandomQueryResultOrderIntegrationTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWPropertyValue as PropertyValue;
+use SMWQuery as Query;
+
+/**
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class RandomQueryResultOrderIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $fixturesProvider;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->fixturesProvider = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesProvider();
+ $this->fixturesProvider->setupDependencies( $this->getStore() );
+ }
+
+ protected function tearDown() {
+
+ $fixturesCleaner = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesCleaner();
+ $fixturesCleaner->purgeAllKnownFacts();
+
+ parent::tearDown();
+ }
+
+ public function testRandomOrder() {
+
+ $factsheet = $this->fixturesProvider->getFactsheet( 'Berlin' );
+ $populationValue = $factsheet->getPopulationValue();
+
+ $this->getStore()->updateData( $factsheet->asEntity() );
+
+ /**
+ * @query [[Population::+]]
+ */
+ $property = $this->fixturesProvider->getProperty( 'Population' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $property );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+ $query->sort = true;
+ $query->sortkeys = [ 'Population' => 'RANDOM' ];
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->assertEquals(
+ 3,
+ $queryResult->getCount()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SortableQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SortableQueryDBIntegrationTest.php
new file mode 100644
index 00000000..65545853
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SortableQueryDBIntegrationTest.php
@@ -0,0 +1,178 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWPropertyValue as PropertyValue;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SortableQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $semanticDataFactory;
+ private $queryResultValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ }
+
+ protected function tearDown() {
+
+ foreach ( $this->subjectsToBeCleared as $subject ) {
+ $this->getStore()->deleteSubject( $subject->getTitle() );
+ }
+
+ parent::tearDown();
+ }
+
+ public function testDefaultSortedQueryResult() {
+
+ $expectedSubjects = [
+ new DIWikiPage( 'AA', NS_MAIN ),
+ new DIWikiPage( 'AB', NS_MAIN ),
+ new DIWikiPage( 'AC', NS_MAIN )
+ ];
+
+ $property = new DIProperty( 'SomePageProperty' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $query = $this->createQueryForSamplePagesThatContain( $property, $expectedSubjects );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $expectedSubjects,
+ $this->getStore()->getQueryResult( $query )
+ );
+ }
+
+ /**
+ * Set limit to avoid:
+ *
+ * Virtuoso 22023 Error SR353: Sorted TOP clause specifies more then 10001
+ * rows to sort. Only 10000 are allowed.
+ *
+ * @see Virtuoso MaxSortedTopRows setting
+ */
+ public function testAscendingOrderedQueryResult() {
+
+ $expectedSubjects = [
+ new DIWikiPage( 'AA', NS_MAIN ),
+ new DIWikiPage( 'AB', NS_MAIN ),
+ new DIWikiPage( 'AC', NS_MAIN )
+ ];
+
+ $property = new DIProperty( 'SomeAscendingPageProperty' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $query = $this->createQueryForSamplePagesThatContain( $property, $expectedSubjects );
+
+ $query->sort = true;
+ $query->sortkeys = [ $property->getKey() => 'ASC' ];
+ $query->setUnboundLimit( 50 );
+
+ $this->assertResultOrder(
+ $expectedSubjects,
+ $this->getStore()->getQueryResult( $query )->getResults()
+ );
+ }
+
+ public function testDescendingOrderedQueryResult() {
+
+ $expectedSubjects = [
+ new DIWikiPage( 'AA', NS_MAIN ),
+ new DIWikiPage( 'AB', NS_MAIN ),
+ new DIWikiPage( 'AC', NS_MAIN )
+ ];
+
+ $property = new DIProperty( 'SomeDescendingPageProperty' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $query = $this->createQueryForSamplePagesThatContain( $property, $expectedSubjects );
+
+ $query->sort = true;
+ $query->sortkeys = [ $property->getKey() => 'DESC' ];
+ $query->setUnboundLimit( 50 );
+
+ $this->assertResultOrder(
+ array_reverse( $expectedSubjects ),
+ $this->getStore()->getQueryResult( $query )->getResults()
+ );
+ }
+
+ public function createQueryForSamplePagesThatContain( $property, array &$expectedSubjects ) {
+
+ foreach ( $expectedSubjects as $key => $expectedSubject ) {
+
+ $subjectTitle = $expectedSubject->getTitle()->getText() . '-' . __METHOD__;
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( $subjectTitle );
+
+ $semanticData->addPropertyObjectValue( $property, $expectedSubject );
+ $this->subjectsToBeCleared[] = $semanticData->getSubject();
+ $expectedSubjects[$key] = $semanticData->getSubject();
+
+ $this->getStore()->updateData( $semanticData );
+ }
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $property );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ return $query;
+ }
+
+ private function assertResultOrder( $expected, $results ) {
+
+ $hasSameOrder = true;
+
+ foreach ( $results as $key => $dataItem ) {
+ if ( $expected[$key]->getHash() !== $dataItem->getHash() ) {
+ $hasSameOrder = false;
+ }
+ }
+
+ $this->assertTrue(
+ $hasSameOrder,
+ 'Failed asserting that results have expected order.'
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SpecialCharactersQueryDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SpecialCharactersQueryDBIntegrationTest.php
new file mode 100644
index 00000000..5237498d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/Query/SpecialCharactersQueryDBIntegrationTest.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace SMW\Tests\Integration\Query;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMW\Subobject;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+use SMWDINumber as DINumber;
+use SMWPropertyValue as PropertyValue;
+use SMWQuery as Query;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group semantic-mediawiki-query
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SpecialCharactersQueryDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjectsToBeCleared = [];
+ private $semanticDataFactory;
+
+ private $dataValueFactory;
+ private $queryResultValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->queryResultValidator = UtilityFactory::getInstance()->newValidatorFactory()->newQueryResultValidator();
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ }
+
+ protected function tearDown() {
+
+ foreach ( $this->subjectsToBeCleared as $subject ) {
+
+ if ( $subject->getTitle() === null ) {
+ continue;
+ }
+
+ $this->getStore()->deleteSubject( $subject->getTitle() );
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider specialCharactersNameProvider
+ */
+ public function testSpecialCharactersInQuery( $subject, $subobjectId, $property, $dataItem ) {
+
+ $dataValue = $this->dataValueFactory->newDataValueByItem(
+ $dataItem,
+ $property
+ );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( $subject );
+ $semanticData->addDataValue( $dataValue );
+
+ $subobject = new Subobject( $semanticData->getSubject()->getTitle() );
+ $subobject->setEmptyContainerForId( $subobjectId );
+
+ $subobject->addDataValue( $dataValue );
+ $semanticData->addSubobject( $subobject );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( $property );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ [
+ $semanticData->getSubject(),
+ $subobject->getSubject() ],
+ $this->getStore()->getQueryResult( $query )
+ );
+
+ $this->queryResultValidator->assertThatQueryResultContains(
+ $dataValue,
+ $this->getStore()->getQueryResult( $query )
+ );
+
+ $this->subjectsToBeCleared = [
+ $semanticData->getSubject(),
+ $subobject->getSubject(),
+ $property->getDIWikiPage()
+ ];
+ }
+
+ public function specialCharactersNameProvider() {
+
+ $provider[] = [
+ '特殊文字',
+ 'Nuñez',
+ DIProperty::newFromUserLabel( '特殊文字' )->setPropertyTypeId( '_txt' ),
+ new DIBlob( 'Nuñez' )
+ ];
+
+ $provider[] = [
+ '特殊字符',
+ '^[0-9]*$',
+ DIProperty::newFromUserLabel( '特殊字符' )->setPropertyTypeId( '_txt' ),
+ new DIBlob( '^[0-9]*$' )
+ ];
+
+ $provider[] = [
+ 'Caractères spéciaux',
+ 'Caractères_spéciaux',
+ DIProperty::newFromUserLabel( 'Caractères spéciaux' )->setPropertyTypeId( '_wpg' ),
+ new DIWikiPage( 'âêîôûëïçé', NS_MAIN )
+ ];
+
+ $provider[] = [
+ 'áéíóúñÑü¡¿',
+ 'áéíóúñÑü¡¿',
+ DIProperty::newFromUserLabel( 'áéíóúñÑü¡¿' )->setPropertyTypeId( '_num' ),
+ new DINumber( 8888 )
+ ];
+
+ $provider[] = [
+ 'Foo',
+ '{({[[&,,;-]]})}',
+ DIProperty::newFromUserLabel( '{({[[&,,;-]]})}' )->setPropertyTypeId( '_wpg' ),
+ new DIWikiPage( '{({[[&,,;-]]})}', NS_MAIN )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/QueryResultQueryProcessorIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/QueryResultQueryProcessorIntegrationTest.php
new file mode 100644
index 00000000..977382df
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/QueryResultQueryProcessorIntegrationTest.php
@@ -0,0 +1,214 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWQuery as Query;
+use SMWQueryProcessor as QueryProcessor;
+
+/**
+ * @covers \SMWQueryResult
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class QueryResultQueryProcessorIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $subjects = [];
+ private $semanticDataFactory;
+
+ private $dataValueFactory;
+ private $queryResultValidator;
+
+ private $fixturesProvider;
+ private $queryParser;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = UtilityFactory::getInstance();
+
+ $this->semanticDataFactory = $utilityFactory->newSemanticDataFactory();
+ $this->queryResultValidator = $utilityFactory->newValidatorFactory()->newQueryResultValidator();
+
+ $this->fixturesProvider = $utilityFactory->newFixturesFactory()->newFixturesProvider();
+ $this->fixturesProvider->setupDependencies( $this->getStore() );
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->queryParser = ApplicationFactory::getInstance()->getQueryFactory()->newQueryParser();
+ }
+
+ protected function tearDown() {
+
+ $fixturesCleaner = UtilityFactory::getInstance()->newFixturesFactory()->newFixturesCleaner();
+
+ $fixturesCleaner
+ ->purgeSubjects( $this->subjects )
+ ->purgeAllKnownFacts();
+
+ parent::tearDown();
+ }
+
+ public function testUriQueryFromRawParameters() {
+
+ $property = $this->fixturesProvider->getProperty( 'url' );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+ $this->subjects[] = $semanticData->getSubject();
+
+ $dataValue = $this->dataValueFactory->newDataValueByProperty(
+ $property,
+ 'http://example.org/api.php?action=Foo'
+ );
+
+ $semanticData->addDataValue( $dataValue );
+
+ $dataValue = $this->dataValueFactory->newDataValueByProperty(
+ $property,
+ 'http://example.org/Bar 42'
+ );
+
+ $semanticData->addDataValue( $dataValue );
+
+ $this->getStore()->updateData( $semanticData );
+
+ /**
+ * @query [[Url::http://example.org/api.php?action=Foo]][[Url::http://example.org/Bar 42]]
+ */
+ $rawParams = [
+ '[[Url::http://example.org/api.php?action=Foo]][[Url::http://example.org/Bar 42]]',
+ '?Url',
+ 'limit=1'
+ ];
+
+ list( $queryString, $parameters, $printouts ) = QueryProcessor::getComponentsFromFunctionParams(
+ $rawParams,
+ false
+ );
+
+ $description = $this->queryParser->getQueryDescription( $queryString );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $queryResult = $this->getStore()->getQueryResult( $query );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $semanticData->getSubject(),
+ $queryResult
+ );
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testCanConstructor( array $test ) {
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $this->getQueryResultFor( $test['query'] )
+ );
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testToArray( array $test, array $expected ) {
+
+ $instance = $this->getQueryResultFor( $test['query'] );
+ $results = $instance->toArray();
+
+ $this->assertEquals( $expected[0], $results['printrequests'][0] );
+ $this->assertEquals( $expected[1], $results['printrequests'][1] );
+ }
+
+ private function getQueryResultFor( $queryString ) {
+
+ list( $query, $formattedParams ) = QueryProcessor::getQueryAndParamsFromFunctionParams(
+ $queryString,
+ SMW_OUTPUT_WIKI,
+ QueryProcessor::INLINE_QUERY,
+ false
+ );
+
+ return $this->getStore()->getQueryResult( $query );
+ }
+
+ public function queryDataProvider() {
+
+ $provider = [];
+
+ // #1 Standard query
+ $provider[] =[
+ [ 'query' => [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'limit=10'
+ ]
+ ],
+ [
+ [
+ 'label'=> '',
+ 'typeid' => '_wpg',
+ 'mode' => 2,
+ 'format' => false,
+ 'key' => '',
+ 'redi' => ''
+ ],
+ [
+ 'label'=> 'Modification date',
+ 'typeid' => '_dat',
+ 'mode' => 1,
+ 'format' => '',
+ 'key' => '_MDAT',
+ 'redi' => ''
+ ]
+ ]
+ ];
+
+ // #2 Query containing a printrequest formatting
+ $provider[] =[
+ [ 'query' => [
+ '[[Modification date::+]]',
+ '?Modification date#ISO',
+ 'limit=10'
+ ]
+ ],
+ [
+ [
+ 'label'=> '',
+ 'typeid' => '_wpg',
+ 'mode' => 2,
+ 'format' => false,
+ 'key' => '',
+ 'redi' => ''
+ ],
+ [
+ 'label'=> 'Modification date',
+ 'typeid' => '_dat',
+ 'mode' => 1,
+ 'format' => 'ISO',
+ 'key' => '_MDAT',
+ 'redi' => ''
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/RdfFileResourceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/RdfFileResourceTest.php
new file mode 100644
index 00000000..131d3c82
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/RdfFileResourceTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMWExportController as ExportController;
+use SMWRDFXMLSerializer as RDFXMLSerializer;
+use Title;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class RdfFileResourceTest extends MwDBaseUnitTestCase {
+
+ private $fixturesFileProvider;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+
+ $this->fixturesFileProvider = $utilityFactory->newFixturesFactory()->newFixturesFileProvider();
+ $this->stringValidator = $utilityFactory->newValidatorFactory()->newStringValidator();
+
+ $this->testEnvironment->withConfiguration( [
+ 'smwgPageSpecialProperties' => [ '_MEDIA', '_MIME' ],
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true, NS_FILE => true ],
+ 'smwgMainCacheType' => 'hash',
+ 'smwgExportBCAuxiliaryUse' => true
+ ] );
+
+ // Ensure that the DB creates the extra tables for MEDIA/MINE
+ $this->getStore()->clear();
+ $this->getStore()->setupStore( false );
+
+ // MW GLOBALS to be restored after the test
+ $this->testEnvironment->withConfiguration( [
+ 'wgEnableUploads' => true,
+ 'wgFileExtensions' => [ 'txt' ],
+ 'wgVerifyMimeType' => true
+ ] );
+
+ \SMWExporter::clear();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testFileUploadForDummyTextFile() {
+ Localizer::getInstance()->clear();
+
+ $subject = new DIWikiPage( 'RdfLinkedFile.txt', NS_FILE );
+ $fileNS = Localizer::getInstance()->getNamespaceTextById( NS_FILE );
+
+ $dummyTextFile = $this->fixturesFileProvider->newUploadForDummyTextFile(
+ 'RdfLinkedFile.txt'
+ );
+
+ $dummyTextFile->doUpload(
+ '[[HasFile::File:RdfLinkedFile.txt]]'
+ );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $exportController = new ExportController( new RDFXMLSerializer() );
+ $exportController->enableBacklinks( false );
+
+ ob_start();
+
+ $exportController->printPages(
+ [ $subject->getTitle()->getPrefixedDBKey() ]
+ );
+
+ $output = ob_get_clean();
+
+ $expected = [
+ "<rdfs:label>{$fileNS}:RdfLinkedFile.txt</rdfs:label>",
+ '<swivt:file rdf:resource="' . $dummyTextFile->getLocalFile()->getFullURL() . '"/>',
+ '<property:Media_type-23aux rdf:datatype="http://www.w3.org/2001/XMLSchema#string">TEXT</property:Media_type-23aux>',
+ '<property:MIME_type-23aux rdf:datatype="http://www.w3.org/2001/XMLSchema#string">text/plain</property:MIME_type-23aux>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $output
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/QueryResultLookupWithoutBaseStoreIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/QueryResultLookupWithoutBaseStoreIntegrationTest.php
new file mode 100644
index 00000000..af941ae4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/QueryResultLookupWithoutBaseStoreIntegrationTest.php
@@ -0,0 +1,219 @@
+<?php
+
+namespace SMW\Tests\Integration\SPARQLStore;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\NamespaceDescription as NamespaceDescription;
+use SMW\Query\Language\SomeProperty as SomeProperty;
+use SMW\Query\Language\ThingDescription as ThingDescription;
+use SMW\Query\Language\ValueDescription as ValueDescription;
+use SMW\SPARQLStore\SPARQLStore;
+use SMW\Subobject;
+use SMW\Tests\Utils\SemanticDataFactory;
+use SMW\Tests\Utils\Validators\QueryResultValidator;
+use SMWDINumber as DINumber;
+use SMWQuery as Query;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class QueryResultLookupWithoutBaseStoreIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ private $store = null;
+ private $queryResultValidator;
+ private $semanticDataFactory;
+ private $dataValueFactory;
+
+ protected function setUp() {
+
+ $this->store = ApplicationFactory::getInstance()->getStore();
+
+ if ( !$this->store instanceof SPARQLStore ) {
+ $this->markTestSkipped( "Requires a SPARQLStore instance" );
+ }
+
+ $repositoryConnection = $this->store->getConnection( 'sparql' );
+ $repositoryConnection->setConnectionTimeout( 5 );
+
+ if ( !$repositoryConnection->ping() ) {
+ $this->markTestSkipped( "Can't connect to the SPARQL repository" );
+ }
+
+ $repositoryConnection->deleteAll();
+
+ $this->queryResultValidator = new QueryResultValidator();
+ $this->semanticDataFactory = new SemanticDataFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ ApplicationFactory::getInstance()->singleton( 'CachedQueryResultPrefetcher' )->disableCache();
+ }
+
+ public function testQuerySubjects_afterUpdatingSemanticData() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $this->store->doSparqlDataUpdate( $semanticData );
+
+ $query = new Query(
+ new ValueDescription( $semanticData->getSubject() ),
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $semanticData->getSubject(),
+ $this->store->getQueryResult( $query )
+ );
+ }
+
+ public function testQueryZeroResults_afterSubjectRemoval() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $property = new DIProperty( __METHOD__ );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByProperty( $property, 'Bar' )
+ );
+
+ $this->store->doSparqlDataUpdate( $semanticData );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $this->assertEquals(
+ 1,
+ $this->store->getQueryResult( $query )->getCount()
+ );
+
+ $this->assertTrue(
+ $this->store->doSparqlDataDelete( $semanticData->getSubject() )
+ );
+
+ $this->assertEquals(
+ 0,
+ $this->store->getQueryResult( $query )->getCount()
+ );
+ }
+
+ /**
+ * @see http://semantic-mediawiki.org/wiki/Help:Selecting_pages#Restricting_results_to_a_namespace
+ */
+ public function testQuerySubjects_onNamspaceRestrictedCondition() {
+
+ $subjectInHelpNamespace = new DIWikiPage( __METHOD__, NS_HELP, '' );
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( $subjectInHelpNamespace )
+ ->newEmptySemanticData();
+
+ $property = new DIProperty( 'SomePageTypePropertyForNamespaceAnnotation' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByProperty( $property, 'Bar' )
+ );
+
+ $this->store->doSparqlDataUpdate( $semanticData );
+
+ $query = new Query(
+ new NamespaceDescription( NS_HELP ),
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $subjectInHelpNamespace,
+ $this->store->getQueryResult( $query )
+ );
+
+ $this->assertTrue(
+ $this->store->doSparqlDataDelete( $semanticData->getSubject() )
+ );
+
+ $this->assertSame(
+ 0,
+ $this->store->getQueryResult( $query )->getCount()
+ );
+ }
+
+ public function testQuerySubobjects_afterUpdatingWithEmptyContainerAllAssociatedEntitiesGetRemovedFromGraph() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $subobject = new Subobject( $semanticData->getSubject()->getTitle() );
+ $subobject->setEmptyContainerForId( 'SubobjectToTestReferenceAfterUpdate' );
+
+ $property = new DIProperty( 'SomeNumericPropertyToCompareReference' );
+ $property->setPropertyTypeId( '_num' );
+
+ $dataItem = new DINumber( 99999 );
+
+ $subobject->addDataValue(
+ $this->dataValueFactory->newDataValueByItem( $dataItem, $property )
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $this->store->doSparqlDataUpdate( $semanticData );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( $dataItem, null, SMW_CMP_EQ )
+ );
+
+ $query = new Query(
+ $description,
+ false,
+ false
+ );
+
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $this->assertSame(
+ 1,
+ $this->store->getQueryResult( $query )->getCount()
+ );
+
+ $this->queryResultValidator->assertThatQueryResultHasSubjects(
+ $subobject->getSemanticData()->getSubject(),
+ $this->store->getQueryResult( $query )
+ );
+
+ $this->store->doSparqlDataUpdate(
+ $this->semanticDataFactory->newEmptySemanticData( __METHOD__ )
+ );
+
+ $this->assertSame(
+ 0,
+ $this->store->getQueryResult( $query )->getCount()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/RepositoryRedirectLookupActiveConnectionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/RepositoryRedirectLookupActiveConnectionTest.php
new file mode 100644
index 00000000..4e53d3f3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SPARQLStore/RepositoryRedirectLookupActiveConnectionTest.php
@@ -0,0 +1,111 @@
+<?php
+
+namespace SMW\Tests\Integration\SPARQLStore;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SPARQLStore\RepositoryRedirectLookup;
+use SMW\SPARQLStore\SPARQLStore;
+use SMWExpNsResource as ExpNsResource;
+use SMWExporter as Exporter;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class RepositoryRepositoryRedirectLookupActiveConnectionTest extends \PHPUnit_Framework_TestCase {
+
+ private $repositoryConnection;
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = ApplicationFactory::getInstance()->getStore();
+
+ if ( !$this->store instanceof SPARQLStore ) {
+ $this->markTestSkipped( "Skipping test because a SPARQLStore instance is required." );
+ }
+
+ $this->repositoryConnection = $this->store->getConnection( 'sparql' );
+ $this->repositoryConnection->setConnectionTimeout( 5 );
+
+ if ( !$this->repositoryConnection->ping() ) {
+ $this->markTestSkipped( "Can't connect to the RepositoryConnector" );
+ }
+ }
+
+ /**
+ * @dataProvider resourceProvider
+ */
+ public function testRedirectTargetLookupForNonExistingEntry( $expNsResource ) {
+
+ $instance = new RepositoryRedirectLookup( $this->repositoryConnection );
+ $instance->reset();
+
+ $exists = null;
+
+ $this->assertSame(
+ $expNsResource,
+ $instance->findRedirectTargetResource( $expNsResource, $exists )
+ );
+
+ $this->assertFalse( $exists );
+ }
+
+ public function testRedirectTargetLookupForExistingEntry() {
+
+ $property = new DIProperty( 'TestRepositoryRedirectLookup' );
+
+ $semanticData = new SemanticData( new DIWikiPage( __METHOD__, NS_MAIN ) );
+
+ $semanticData->addDataValue(
+ DataValueFactory::getInstance()->newDataValueByProperty( $property, 'Bar' )
+ );
+
+ $this->store->doSparqlDataUpdate( $semanticData );
+
+ $expNsResource = new ExpNsResource(
+ 'TestRepositoryRedirectLookup',
+ Exporter::getInstance()->getNamespaceUri( 'property' ),
+ 'property'
+ );
+
+ $instance = new RepositoryRedirectLookup( $this->repositoryConnection );
+ $instance->reset();
+
+ $exists = null;
+
+ $this->assertSame(
+ $expNsResource,
+ $instance->findRedirectTargetResource( $expNsResource, $exists )
+ );
+
+ $this->assertTrue( $exists );
+ }
+
+ public function resourceProvider() {
+
+ $provider[] = [
+ Exporter::getInstance()->getSpecialNsResource( 'rdf', 'type' )
+ ];
+
+ $provider[] = [
+ new ExpNsResource(
+ 'FooRepositoryRedirectLookup',
+ Exporter::getInstance()->getNamespaceUri( 'property' ),
+ 'property',
+ new DIWikiPage( 'FooRepositoryRedirectLookup', SMW_NS_PROPERTY, '' )
+ )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/RefreshSQLStoreDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/RefreshSQLStoreDBIntegrationTest.php
new file mode 100644
index 00000000..6498c0ad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/RefreshSQLStoreDBIntegrationTest.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace SMW\Tests\Integration\SQLStore;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\MwHooksHandler;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Tests\Utils\PageDeleter;
+use Title;
+use WikiPage;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class RefreshSQLStoreDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $title;
+ private $mwHooksHandler;
+ private $pageDeleter;
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mwHooksHandler = new MwHooksHandler();
+ $this->pageDeleter = new PageDeleter();
+ $this->pageCreator = new PageCreator();
+ }
+
+ public function tearDown() {
+
+ $this->mwHooksHandler->restoreListedHooks();
+
+ if ( $this->title !== null ) {
+ $this->pageDeleter->deletePage( $this->title );
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testAfterPageCreation_StoreHasDataToRefreshWithoutJobs( $ns, $name, $iw ) {
+
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->title = Title::makeTitle( $ns, $name, '', $iw );
+
+ $this->pageCreator->createPage( $this->title );
+
+ $this->assertStoreHasDataToRefresh( false );
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testAfterPageCreation_StoreHasDataToRefreshWitJobs( $ns, $name, $iw ) {
+
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->title = Title::makeTitle( $ns, $name, '', $iw );
+
+ $this->pageCreator->createPage( $this->title );
+
+ $this->assertStoreHasDataToRefresh( true );
+ }
+
+ protected function assertStoreHasDataToRefresh( $useJobs ) {
+ $refreshPosition = $this->title->getArticleID();
+
+ $entityRebuildDispatcher = $this->getStore()->refreshData(
+ $refreshPosition,
+ 1,
+ false,
+ $useJobs
+ );
+
+ $entityRebuildDispatcher->rebuild( $refreshPosition );
+
+ $this->assertGreaterThan(
+ 0,
+ $entityRebuildDispatcher->getEstimatedProgress()
+ );
+ }
+
+ public function titleProvider() {
+ $provider = [];
+
+ // $provider[] = array( NS_MAIN, 'withInterWiki', 'commons' );
+ $provider[] = [ NS_MAIN, 'normalTite', '' ];
+ $provider[] = [ NS_MAIN, 'useUpdateJobs', '' ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/SubSemanticDataDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/SubSemanticDataDBIntegrationTest.php
new file mode 100644
index 00000000..f6144827
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/SubSemanticDataDBIntegrationTest.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\Integration\SQLStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Tests\Utils\PageDeleter;
+use SMW\Tests\Utils\Validators\SemanticDataValidator;
+use Title;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-database
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SubSemanticDataDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $title;
+
+ protected function tearDown() {
+ $pageDeleter= new PageDeleter();
+
+ $pageDeleter->deletePage( $this->title );
+
+ parent::tearDown();
+ }
+
+ public function testCreatePageWithSubobject() {
+
+ $this->title = Title::newFromText( __METHOD__ );
+
+ $pageCreator = new PageCreator();
+
+ $pageCreator
+ ->createPage( $this->title )
+ ->doEdit(
+ '{{#subobject:namedSubobject|AA=Test1|@sortkey=Z}}' .
+ '{{#subobject:|BB=Test2|@sortkey=Z}}' );
+
+ $semanticData = $this->getStore()->getSemanticData( DIWikiPage::newFromTitle( $this->title ) );
+
+ $this->assertInstanceOf(
+ 'SMW\SemanticData',
+ $semanticData->findSubSemanticData( 'namedSubobject' )
+ );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( 'AA' ),
+ new DIProperty( 'BB' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [
+ 'Test1',
+ 'Test2',
+ 'Z'
+ ]
+ ];
+
+ $semanticDataValidator = new SemanticDataValidator();
+
+ foreach ( $semanticData->getSubSemanticData() as $subSemanticData ) {
+ $semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $subSemanticData
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/TableBuilder/TableBuilderIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/TableBuilder/TableBuilderIntegrationTest.php
new file mode 100644
index 00000000..535b3faf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SQLStore/TableBuilder/TableBuilderIntegrationTest.php
@@ -0,0 +1,318 @@
+<?php
+
+namespace SMW\Tests\Integration\SQLStore\TableBuilder;
+
+use Onoi\MessageReporter\MessageReporterFactory;
+use SMW\SQLStore\TableBuilder\FieldType;
+use SMW\SQLStore\TableBuilder\PostgresTableBuilder;
+use SMW\SQLStore\TableBuilder\SQLiteTableBuilder;
+use SMW\SQLStore\TableBuilder\Table;
+use SMW\SQLStore\TableBuilder\TableBuilder;
+use SMW\Tests\MwDBaseUnitTestCase;
+
+/**
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TableBuilderIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $messageReporterFactory;
+ private $TableBuilder;
+ private $stringValidator;
+ private $tableName = 'rdbms_test';
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->messageReporterFactory = MessageReporterFactory::getInstance();
+
+ $this->tableBuilder = TableBuilder::factory(
+ $this->getStore()->getConnection( DB_MASTER )
+ );
+
+ $this->stringValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testCreateTable() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+ $table->addColumn( 'id', FieldType::FIELD_ID_PRIMARY );
+ $table->addColumn( 't_text', [ FieldType::TYPE_BLOB, 'NOT NULL' ] );
+
+ $this->tableBuilder->create( $table );
+
+ $expected = [
+ 'Checking table rdbms_test',
+ 'Table not found, now creating',
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testUpdateTableWithNewField() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+ $table->addColumn( 'id', FieldType::FIELD_ID_PRIMARY );
+ $table->addColumn( 't_text', [ FieldType::TYPE_BLOB, 'NOT NULL' ] );
+ $table->addColumn( 't_num', [ FieldType::TYPE_INT, 'NOT NULL' ] );
+ $table->addColumn( 't_int', [ FieldType::TYPE_INT ] );
+
+ $this->tableBuilder->create( $table );
+
+ $expected = [
+ 'Checking table rdbms_test',
+ 'Table already exists, checking structure',
+ 'creating field t_num',
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testUpdateTableWithNewFieldType() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+ $table->addColumn( 'id', FieldType::FIELD_ID_PRIMARY );
+ $table->addColumn( 't_text', [ FieldType::TYPE_BLOB, 'NOT NULL' ] );
+ $table->addColumn( 't_num', [ FieldType::TYPE_DOUBLE, 'NOT NULL' ] );
+ $table->addColumn( 't_int', [ FieldType::TYPE_INT ] );
+
+ $this->tableBuilder->create( $table );
+
+ $expected = [
+ 'Checking table rdbms_test',
+ 'Table already exists, checking structure',
+ 'changing type of field t_num',
+ ];
+
+ // Not supported
+ if ( $this->tableBuilder instanceof SQLiteTableBuilder ) {
+ $expected = str_replace( 'changing type of field t_num', 'changing field type is not supported', $expected );
+ }
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testCreateIndex() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+ $table->addColumn( 'id', FieldType::FIELD_ID_PRIMARY );
+ $table->addColumn( 't_text', [ FieldType::TYPE_BLOB, 'NOT NULL' ] );
+ $table->addColumn( 't_num', [ FieldType::TYPE_DOUBLE, 'NOT NULL' ] );
+ $table->addColumn( 't_int', [ FieldType::TYPE_INT ] );
+
+ $table->addIndex( 'id' );
+ $table->addIndex( 't_int' );
+ $table->addIndex( 't_num' );
+
+ $this->tableBuilder->create( $table );
+
+ $expected = [
+ 'Checking index structures for table rdbms_test',
+ 'index id is fine',
+ 'creating new index t_num'
+ ];
+
+ // ID message, Primary doesn't implicitly exists before
+ if ( $this->tableBuilder instanceof PostgresTableBuilder || $this->tableBuilder instanceof SQLiteTableBuilder ) {
+ $expected = str_replace( 'index id is fine', 'creating new index id', $expected );
+ }
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testUpdateIndex_ReplaceIndex() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+ $table->addColumn( 'id', FieldType::FIELD_ID_PRIMARY );
+ $table->addColumn( 't_text', [ FieldType::TYPE_BLOB, 'NOT NULL' ] );
+ $table->addColumn( 't_num', [ FieldType::TYPE_DOUBLE, 'NOT NULL' ] );
+ $table->addColumn( 't_int', [ FieldType::TYPE_INT ] );
+
+ $table->addIndex( 'id' );
+ $table->addIndex( 't_num,t_int' );
+
+ $this->tableBuilder->create( $table );
+
+ $expected = [
+ 'Checking index structures for table rdbms_test',
+ 'index id is fine',
+ 'removing index t_num',
+ 'creating new index t_num,t_int',
+ ];
+
+ if ( $this->tableBuilder instanceof SQLiteTableBuilder ) {
+ $expected = str_replace( 'index id is fine', 'creating new index id', $expected );
+ $expected = 'removing index';
+ }
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testUpdateIndex_RemoveIndexWithArrayNotation() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+ $table->addColumn( 'id', FieldType::FIELD_ID_PRIMARY );
+ $table->addColumn( 't_text', [ FieldType::TYPE_BLOB, 'NOT NULL' ] );
+ $table->addColumn( 't_num', [ FieldType::TYPE_DOUBLE, 'NOT NULL' ] );
+ $table->addColumn( 't_int', [ FieldType::TYPE_INT ] );
+
+ $table->addIndex( [ 'id', 'UNIQUE INDEX' ] );
+
+ $this->tableBuilder->create( $table );
+
+ $expected = [
+ 'Checking index structures for table rdbms_test',
+ 'index id is fine',
+ 'removing index t_num,t_int'
+ ];
+
+ if ( $this->tableBuilder instanceof SQLiteTableBuilder ) {
+ $expected = str_replace( 'index id is fine', 'creating new index id', $expected );
+ $expected = 'removing index';
+ }
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testUpdateIndex_NoIndexChange() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+ $table->addColumn( 'id', FieldType::FIELD_ID_PRIMARY );
+ $table->addColumn( 't_text', [ FieldType::TYPE_BLOB, 'NOT NULL' ] );
+ $table->addColumn( 't_num', [ FieldType::TYPE_DOUBLE, 'NOT NULL' ] );
+ $table->addColumn( 't_int', [ FieldType::TYPE_INT ] );
+
+ $table->addIndex( [ 'id', 'UNIQUE INDEX' ] );
+
+ $this->tableBuilder->create( $table );
+
+ $expected = [
+ 'Checking index structures for table rdbms_test',
+ 'index id is fine'
+ ];
+
+ if ( $this->tableBuilder instanceof SQLiteTableBuilder ) {
+ $expected = str_replace( 'index id is fine', 'creating new index id', $expected );
+ $expected = 'removing index';
+ }
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testDropTable() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( $this->tableName );
+
+ $this->tableBuilder->drop( $table );
+
+ $expected = [
+ 'dropped table rdbms_test'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testTryToDropTableWhichNotExists() {
+
+ $messageReporter = $this->messageReporterFactory->newSpyMessageReporter();
+
+ $this->tableBuilder->setMessageReporter(
+ $messageReporter
+ );
+
+ $table = new Table( 'foo_test' );
+
+ $this->tableBuilder->drop( $table );
+
+ $expected = [
+ 'foo_test not found, skipping removal'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $messageReporter->getMessagesAsString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializationDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializationDBIntegrationTest.php
new file mode 100644
index 00000000..e705afd9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializationDBIntegrationTest.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SerializerFactory;
+use SMW\Subobject;
+use SMW\Tests\MwDBaseUnitTestCase;
+use Title;
+
+/**
+ * @group semantic-mediawiki-integration
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SemanticDataSerializationDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ public function testRoundtripOfSerializedSemanticDataAfterStoreUpdate() {
+
+ $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+ $semanticDataBeforeUpdate = new SemanticData( $subject );
+
+ $subobject = new Subobject( $subject->getTitle() );
+ $subobject->setEmptyContainerForId( 'SomeSubobjectToSerialize' );
+
+ $subobject->getSemanticData()->addDataValue(
+ DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $semanticDataBeforeUpdate->addSubobject( $subobject );
+
+ $this->getStore()->updateData( $semanticDataBeforeUpdate );
+
+ $semanticDataAfterUpdate = $this->getStore()->getSemanticData( $subject );
+
+ $serializerFactory = new SerializerFactory();
+
+ $serialization = $serializerFactory->getSerializerFor( $semanticDataAfterUpdate )->serialize( $semanticDataAfterUpdate );
+
+ $this->assertEquals(
+ $semanticDataAfterUpdate->getHash(),
+ $serializerFactory->getDeserializerFor( $serialization )->deserialize( $serialization )->getHash()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializerDeserializerRoundtripTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializerDeserializerRoundtripTest.php
new file mode 100644
index 00000000..9e13a517
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSerializerDeserializerRoundtripTest.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use ReflectionClass;
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\Deserializers\SemanticDataDeserializer;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\Serializers\SemanticDataSerializer;
+use SMW\Subobject;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SemanticDataSerializerDeserializerRoundtripTest extends \PHPUnit_Framework_TestCase {
+
+ private function newSerializerInstance() {
+ return new SemanticDataSerializer();
+ }
+
+ private function newDeserializerInstance() {
+ return new SemanticDataDeserializer();
+ }
+
+ /**
+ * @dataProvider semanticDataProvider
+ */
+ public function testSerializerDeserializerRountrip( $data ) {
+
+ $serialized = $this->newSerializerInstance()->serialize( $data );
+
+ $this->assertEquals(
+ $serialized,
+ $this->newSerializerInstance()->serialize( $this->newDeserializerInstance()->deserialize( $serialized ) )
+ );
+
+
+ $this->assertEquals(
+ $data->getHash(),
+ $this->newDeserializerInstance()->deserialize( $serialized )->getHash()
+ );
+ }
+
+ /**
+ * @dataProvider incompleteSubobjectDataProvider
+ */
+ public function testSerializerDeserializerWithIncompleteSubobjectData( $data ) {
+
+ $serialized = $this->newSerializerInstance()->serialize( $data );
+
+ $this->assertInstanceOf(
+ 'SMW\SemanticData',
+ $this->newDeserializerInstance()->deserialize( $serialized )
+ );
+ }
+
+ /**
+ * @dataProvider typeChangeSemanticDataProvider
+ */
+ public function testForcedTypeErrorDuringRountrip( $data, $type ) {
+
+ $serialized = $this->newSerializerInstance()->serialize( $data );
+ $deserializer = $this->newDeserializerInstance();
+
+ // Injects a different type to cause an error (this would normally
+ // happen when a property definition is changed such as page -> text
+ // etc.)
+ $reflector = new ReflectionClass( '\SMW\Deserializers\SemanticDataDeserializer' );
+ $property = $reflector->getProperty( 'dataItemTypeIdCache' );
+ $property->setAccessible( true );
+ $property->setValue( $deserializer, [ $type => 2 ] );
+
+ $deserialized = $deserializer->deserialize( $serialized );
+
+ $this->assertInstanceOf(
+ 'SMW\SemanticData',
+ $deserialized
+ );
+
+ $this->assertNotEmpty(
+ $deserialized->getErrors()
+ );
+ }
+
+ public function semanticDataProvider() {
+
+ ApplicationFactory::clear();
+
+ $provider = [];
+ $title = \Title::newFromText( __METHOD__ );
+
+ // #0 Empty container
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $provider[] = [ $foo ];
+
+ // #1 Single entry
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+ $provider[] = [ $foo ];
+
+ // #2 Single + single subobject entry
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has subobjects', 'Bam' ) );
+
+ $foo->addPropertyObjectValue( $subobject->getProperty(), $subobject->getContainer() );
+
+ $provider[] = [ $foo ];
+
+ // #3 Multiple entries
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+ $foo->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has queez', 'Xeey' ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has subobjects', 'Bam' ) );
+ $subobject->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Fuz' ) );
+
+ $subobject->setSemanticData( 'Bar' );
+ $subobject->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Fuz' ) );
+
+ $foo->addPropertyObjectValue( $subobject->getProperty(), $subobject->getContainer() );
+
+ $provider[] = [ $foo ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function incompleteSubobjectDataProvider() {
+
+ $provider = [];
+
+ $title = \Title::newFromText( __METHOD__ );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+ $foo->addPropertyObjectValue( $subobject->getProperty(), $subobject->getSemanticData()->getSubject() );
+
+ $provider[] = [ $foo ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function typeChangeSemanticDataProvider() {
+
+ $provider = [];
+ $title = \Title::newFromText( __METHOD__ );
+
+ // #0 Single entry
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+
+ $provider[] = [ $foo, 'Has_fooQuex' ];
+
+ // #1 Single subobject entry
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fomQuex', 'Bam' ) );
+
+ $foo->addPropertyObjectValue( $subobject->getProperty(), $subobject->getContainer() );
+
+ $provider[] = [ $foo, 'Has_fomQuex' ];
+
+ // #2 Combined
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+ $foo->addPropertyObjectValue( $subobject->getProperty(), $subobject->getContainer() );
+
+ $provider[] = [ $foo, 'Has_fomQuex' ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSortKeyUpdateDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSortKeyUpdateDBIntegrationTest.php
new file mode 100644
index 00000000..6af6b620
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataSortKeyUpdateDBIntegrationTest.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\DIProperty;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-database
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SemanticDataSortKeyUpdateDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $semanticDataFactory;
+ private $subjects = [];
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+
+ $this->mwHooksHandler = UtilityFactory::getInstance()->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+ }
+
+ protected function tearDown() {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $this->subjects );
+ $this->mwHooksHandler->restoreListedHooks();
+
+ parent::tearDown();
+ }
+
+ public function testSubjectSortKeySetter() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $subject = $semanticData->getSubject();
+ $subject->setSortKey( 'a_b_c' );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $semanticDataFromDB = $this->getStore()->getSemanticData( $subject );
+
+ $this->assertEquals(
+ 'a b c',
+ $semanticDataFromDB->getSubject()->getSortKey()
+ );
+
+ foreach ( $semanticDataFromDB->getPropertyValues( new DIProperty( '_SKEY' ) ) as $value ) {
+ $this->assertEquals(
+ 'a b c',
+ $value->getString()
+ );
+ }
+
+ $this->subjects[] = $semanticData->getSubject();
+ }
+
+ public function testDefinedSortKeyTakesPrecedenceOverSubjectSortKey() {
+
+ $semanticData = $this->semanticDataFactory
+ ->newEmptySemanticData( __METHOD__ );
+
+ $subject = $semanticData->getSubject();
+ $subject->setSortKey( '1_2_3' );
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_SKEY' ),
+ new DIBlob( 'x_y_z' )
+ );
+
+ $this->getStore()->updateData( $semanticData );
+ $this->getStore()->clear();
+
+ $semanticDataFromDB = $this->getStore()->getSemanticData( $subject );
+
+ $this->assertEquals(
+ 'x y z',
+ $semanticDataFromDB->getSubject()->getSortKey()
+ );
+
+ foreach ( $semanticDataFromDB->getPropertyValues( new DIProperty( '_SKEY' ) ) as $value ) {
+ $this->assertEquals(
+ 'x y z',
+ $value->getString()
+ );
+ }
+
+ $this->subjects[] = $semanticData->getSubject();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataStorageDBIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataStorageDBIntegrationTest.php
new file mode 100644
index 00000000..0938c9a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticDataStorageDBIntegrationTest.php
@@ -0,0 +1,327 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\Subobject;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+use SMWDITime as DITime;
+use Title;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-database
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SemanticDataStorageDBIntegrationTest extends MwDBaseUnitTestCase {
+
+ private $applicationFactory;
+ private $mwHooksHandler;
+
+ private $semanticDataValidator;
+ private $subjects = [];
+
+ private $pageDeleter;
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = UtilityFactory::getInstance();
+
+ $this->mwHooksHandler = $utilityFactory->newMwHooksHandler();
+
+ $this->mwHooksHandler
+ ->deregisterListedHooks()
+ ->invokeHooksFromRegistry();
+
+ $this->semanticDataValidator = $utilityFactory->newValidatorFactory()->newSemanticDataValidator();
+ $this->pageDeleter = $utilityFactory->newPageDeleter();
+ $this->pageCreator = $utilityFactory->newPageCreator();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+
+ $this->pageDeleter
+ ->doDeletePoolOfPages( $this->subjects );
+
+ $this->applicationFactory->clear();
+ $this->mwHooksHandler->restoreListedHooks();
+
+ parent::tearDown();
+ }
+
+ public function testUserDefined_PageProperty_ToSemanticDataForStorage() {
+
+ $property = new DIProperty( 'SomePageProperty' );
+
+ $this->subjects[] = $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+ $semanticData = new SemanticData( $subject );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( 'SomePropertyPageValue', NS_MAIN, '' )
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->assertArrayHasKey(
+ $property->getKey(),
+ $this->getStore()->getSemanticData( $subject )->getProperties()
+ );
+
+ foreach ( $this->getStore()->getProperties( $subject ) as $prop ) {
+ $this->assertTrue( $prop->equals( $property ) );
+ }
+ }
+
+ public function testFixedProperty_MDAT_ToSemanticDataForStorage() {
+
+ $property = new DIProperty( '_MDAT' );
+
+ $this->subjects[] = $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+ $semanticData = new SemanticData( $subject );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DITime( 1, '1970', '1', '1' )
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->assertArrayHasKey(
+ $property->getKey(),
+ $this->getStore()->getSemanticData( $subject )->getProperties()
+ );
+
+ foreach ( $this->getStore()->getProperties( $subject ) as $prop ) {
+ $this->assertTrue( $prop->equals( $property ) );
+ }
+ }
+
+ public function testFixedProperty_ASK_NotForStorage() {
+
+ $property = new DIProperty( '_ASK' );
+
+ $this->subjects[] = $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+ $semanticData = new SemanticData( $subject );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->assertEmpty(
+ $this->getStore()->getProperties( $subject )
+ );
+ }
+
+ public function testAddUserDefinedBlobPropertyAsObjectToSemanticDataForStorage() {
+
+ $property = new DIProperty( 'SomeBlobProperty' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $this->subjects[] = $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+ $semanticData = new SemanticData( $subject );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DIBlob( 'SomePropertyBlobValue' )
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->assertArrayHasKey(
+ $property->getKey(),
+ $this->getStore()->getSemanticData( $subject )->getProperties()
+ );
+ }
+
+ public function testAddUserDefinedPropertyAsDataValueToSemanticDataForStorage() {
+
+ $propertyAsString = 'SomePropertyAsString';
+
+ $this->subjects[] = $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+ $semanticData = new SemanticData( $subject );
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByText(
+ $propertyAsString,
+ 'Foo',
+ false,
+ $subject
+ );
+
+ $semanticData->addDataValue( $dataValue );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $this->assertArrayHasKey(
+ $propertyAsString,
+ $this->getStore()->getSemanticData( $subject )->getProperties()
+ );
+ }
+
+ public function testAddSubobjectToSemanticDataForStorage() {
+
+ $this->subjects[] = $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+ $semanticData = new SemanticData( $subject );
+
+ $subobject = new Subobject( $subject->getTitle() );
+ $subobject->setEmptyContainerForId( 'SomeSubobject' );
+
+ $subobject->getSemanticData()->addDataValue(
+ DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $this->getStore()->updateData( $semanticData );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( 'Foo' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [ 'Bar', __METHOD__ . '#SomeSubobject' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $this->getStore()->getSemanticData( $subject )->findSubSemanticData( 'SomeSubobject' )
+ );
+ }
+
+ public function testFetchSemanticDataForPreExistingSimpleRedirect() {
+
+ $this->applicationFactory->clear();
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo-B' ) )
+ ->doEdit( '#REDIRECT [[Foo-A]]' );
+
+ $subject = DIWikiPage::newFromTitle( Title::newFromText( 'Foo-A' ) );
+
+ $this->pageCreator
+ ->createPage( $subject->getTitle() )
+ ->doEdit( '[[HasNoDisplayRedirectInconsistencyFor::Foo-B]]' );
+
+ $expected = [
+ 'propertyCount' => 3,
+ 'propertyKeys' => [ '_SKEY', '_MDAT', 'HasNoDisplayRedirectInconsistencyFor' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $this->getStore()->getSemanticData( $subject )
+ );
+
+ $this->subjects = [
+ $subject,
+ Title::newFromText( 'Foo-B' )
+ ];
+ }
+
+ public function testFetchSemanticDataForPreExistingDoubleRedirect() {
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo-B' ) )
+ ->doEdit( '#REDIRECT [[Foo-C]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo-C' ) )
+ ->doEdit( '#REDIRECT [[Foo-A]]' );
+
+ $subject = DIWikiPage::newFromTitle( Title::newFromText( 'Foo-A' ) );
+
+ $this->pageCreator
+ ->createPage( $subject->getTitle() )
+ ->doEdit( '[[HasNoDisplayRedirectInconsistencyFor::Foo-B]]' );
+
+ $this->pageCreator
+ ->createPage( Title::newFromText( 'Foo-C' ) )
+ ->doEdit( '[[Has page::{{PAGENAME}}' );
+
+ $expected = [
+ 'propertyCount' => 3,
+ 'propertyKeys' => [ '_SKEY', '_MDAT', 'HasNoDisplayRedirectInconsistencyFor' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $this->getStore()->getSemanticData( $subject )
+ );
+
+ $this->subjects = [
+ $subject,
+ Title::newFromText( 'Foo-B' ),
+ Title::newFromText( 'Foo-C' )
+ ];
+ }
+
+ /**
+ * Issue 622/619
+ */
+ public function testPrepareToFetchCorrectSemanticDataFromInternalCache() {
+
+ $redirect = DIWikiPage::newFromTitle( Title::newFromText( 'Foo-A' ) );
+
+ $this->pageCreator
+ ->createPage( $redirect->getTitle() )
+ ->doEdit( '#REDIRECT [[Foo-C]]' );
+
+ $target = DIWikiPage::newFromTitle( Title::newFromText( 'Foo-C' ) );
+
+ $this->pageCreator
+ ->createPage( $target->getTitle() )
+ ->doEdit( '{{#subobject:test|HasSomePageProperty=Foo-A}}' );
+
+ $this->assertEmpty(
+ $this->getStore()->getSemanticData( $redirect )->findSubSemanticData( 'test' )
+ );
+
+ $this->assertNotEmpty(
+ $this->getStore()->getSemanticData( $target )->findSubSemanticData( 'test' )
+ );
+ }
+
+ /**
+ * @depends testPrepareToFetchCorrectSemanticDataFromInternalCache
+ */
+ public function testVerifyToFetchCorrectSemanticDataFromInternalCache() {
+
+ $redirect = DIWikiPage::newFromTitle( Title::newFromText( 'Foo-A' ) );
+ $target = DIWikiPage::newFromTitle( Title::newFromText( 'Foo-C' ) );
+
+ $this->assertEmpty(
+ $this->getStore()->getSemanticData( $redirect )->findSubSemanticData( 'test' )
+ );
+
+ $this->assertNotEmpty(
+ $this->getStore()->getSemanticData( $target )->findSubSemanticData( 'test' )
+ );
+
+ $this->subjects = [
+ $redirect,
+ $target
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticMediaWikiProvidedHookInterfaceIntegrationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticMediaWikiProvidedHookInterfaceIntegrationTest.php
new file mode 100644
index 00000000..4a74f0ff
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SemanticMediaWikiProvidedHookInterfaceIntegrationTest.php
@@ -0,0 +1,471 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use RuntimeException;
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SemanticMediaWikiProvidedHookInterfaceIntegrationTest extends \PHPUnit_Framework_TestCase {
+
+ private $mwHooksHandler;
+ private $applicationFactory;
+ private $spyLogger;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyLogger = $this->testEnvironment->newSpyLogger();
+
+ $this->mwHooksHandler = $this->testEnvironment->getUtilityFactory()->newMwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->mwHooksHandler->restoreListedHooks();
+ $this->applicationFactory->clear();
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider storeClassProvider
+ */
+ public function testUnregisteredQueryResultHook( $storeClass ) {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->setMethods( [ 'fetchQueryResult' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'fetchQueryResult' );
+
+ $store->getQueryResult( $query );
+ }
+
+ /**
+ * @dataProvider storeClassProvider
+ */
+ public function testRegisteredStoreBeforeQueryResultLookupCompleteHookToPreFetchQueryResult( $storeClass ) {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->setMethods( [ 'fetchQueryResult' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'fetchQueryResult' );
+
+ $this->mwHooksHandler->register( 'SMW::Store::BeforeQueryResultLookupComplete', function( $store, $query, &$queryResult ) {
+ $queryResult = 'Foo';
+ return true;
+ } );
+
+ $this->assertNotEquals(
+ 'Foo',
+ $store->getQueryResult( $query )
+ );
+ }
+
+ /**
+ * @dataProvider storeClassProvider
+ */
+ public function testRegisteredStoreBeforeQueryResultLookupCompleteHookToSuppressDefaultQueryResultFetch( $storeClass ) {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->setMethods( [ 'fetchQueryResult' ] )
+ ->getMock();
+
+ $store->expects( $this->never() )
+ ->method( 'fetchQueryResult' );
+
+ $this->mwHooksHandler->register( 'SMW::Store::BeforeQueryResultLookupComplete', function( $store, $query, &$queryResult ) {
+
+ $queryResult = 'Foo';
+
+ // Return false to suppress additional calls to fetchQueryResult
+ return false;
+ } );
+
+ $this->assertEquals(
+ 'Foo',
+ $store->getQueryResult( $query )
+ );
+ }
+
+ /**
+ * @dataProvider storeClassProvider
+ */
+ public function testRegisteredStoreAfterQueryResultLookupComplete( $storeClass ) {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->setMethods( [ 'fetchQueryResult' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'fetchQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $this->mwHooksHandler->register( 'SMW::Store::AfterQueryResultLookupComplete', function( $store, &$queryResult ) {
+
+ if ( !$queryResult instanceof \SMWQueryResult ) {
+ throw new RuntimeException( 'Expected a SMWQueryResult instance' );
+ }
+
+ return true;
+ } );
+
+ $store->getQueryResult( $query );
+ }
+
+ /**
+ * @dataProvider storeClassProvider
+ */
+ public function testRegisteredFactboxBeforeContentGenerationToSuppressDefaultTableCreation( $storeClass ) {
+
+ $this->applicationFactory->getSettings()->set( 'smwgShowFactbox', SMW_FACTBOX_NONEMPTY );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( new DIWikiPage( 'Bar', NS_MAIN ) ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'hasVisibleProperties' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSemanticData', 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $this->mwHooksHandler->register( 'SMW::Factbox::BeforeContentGeneration', function( &$text, $semanticData ) {
+ $text = $semanticData->getSubject()->getTitle()->getText();
+ return false;
+ } );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = $this->applicationFactory->singleton( 'FactboxFactory' )->newFactbox( $title, new \ParserOutput() );
+ $instance->doBuild();
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->getContent()
+ );
+ }
+
+ public function testRegisteredSQLStoreBeforeChangeTitleComplete() {
+
+ // To make this work with SPARQLStore, need to inject the basestore
+ $storeClass = '\SMWSQLStore3';
+
+ $title = \Title::newFromText( __METHOD__ );
+
+ $idGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $idGenerator->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->setMethods( [ 'getObjectIds', 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idGenerator ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $null = 0;
+
+ $this->mwHooksHandler->register( 'SMW::SQLStore::BeforeChangeTitleComplete', function( $store, $oldTitle, $newTitle, $pageId, $redirectId ) {
+ return $store->reachedTheBeforeChangeTitleCompleteHook = true;
+ } );
+
+ $store->changeTitle( $title, $title, $null, $null );
+
+ $this->assertTrue(
+ $store->reachedTheBeforeChangeTitleCompleteHook
+ );
+ }
+
+ public function testRegisteredSQLStoreBeforeDeleteSubjectComplete() {
+
+ // To make this work with SPARQLStore, need to inject the basestore
+ $storeClass = '\SMWSQLStore3';
+
+ $title = \Title::newFromText( __METHOD__ );
+
+ $idGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $idGenerator->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [ 42 ] ) );
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->setMethods( [ 'getPropertyTables', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idGenerator ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->mwHooksHandler->register( 'SMW::SQLStore::BeforeDeleteSubjectComplete', function( $store, $title ) {
+ return $store->reachedTheBeforeDeleteSubjectCompleteHook = true;
+ } );
+
+ $store->deleteSubject( $title );
+
+ $this->assertTrue(
+ $store->reachedTheBeforeDeleteSubjectCompleteHook
+ );
+ }
+
+ public function testRegisteredSQLStoreAfterDeleteSubjectComplete() {
+
+ // To make this work with SPARQLStore, need to inject the basestore
+ $storeClass = '\SMWSQLStore3';
+
+ $title = \Title::newFromText( __METHOD__ );
+
+ $idGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $idGenerator->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [ 42 ] ) );
+
+ $store = $this->getMockBuilder( $storeClass )
+ ->setMethods( [ 'getPropertyTables', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idGenerator ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->mwHooksHandler->register( 'SMW::SQLStore::AfterDeleteSubjectComplete', function( $store, $title ) {
+ return $store->reachedTheAfterDeleteSubjectCompleteHook = true;
+ } );
+
+ $store->deleteSubject( $title );
+
+ $this->assertTrue(
+ $store->reachedTheAfterDeleteSubjectCompleteHook
+ );
+ }
+
+ public function testRegisteredParserBeforeMagicWordsFinder() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = \Title::newFromText( __METHOD__ );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserData->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $parserData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromTitle( $title ) ) );
+
+ $parserData->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $parserData->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $magicWordsFinder = $this->getMockBuilder( '\SMW\MediaWiki\MagicWordsFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $magicWordsFinder->expects( $this->once() )
+ ->method( 'findMagicWordInText' )
+ ->with(
+ $this->equalTo( 'Foo' ),
+ $this->anything() )
+ ->will( $this->returnValue( [] ) );
+
+ $linksProcessor = $this->getMockBuilder( '\SMW\Parser\LinksProcessor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $redirectTargetFinder = $this->getMockBuilder( '\SMW\MediaWiki\RedirectTargetFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $inTextAnnotationParser = $this->getMockBuilder( '\SMW\Parser\InTextAnnotationParser' )
+ ->setConstructorArgs( [ $parserData, $linksProcessor, $magicWordsFinder, $redirectTargetFinder ] )
+ ->setMethods( null )
+ ->getMock();
+
+ $this->mwHooksHandler->register( 'SMW::Parser::BeforeMagicWordsFinder', function( &$magicWords ) {
+ $magicWords = [ 'Foo' ];
+
+ // Just to make MW 1.19 happy, otherwise it is not really needed
+ return true;
+ } );
+
+ $text = '';
+
+ $inTextAnnotationParser->parse( $text );
+ }
+
+ public function testRegisteredAddCustomFixedPropertyTables() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( null )
+ ->getMock();
+
+ $this->mwHooksHandler->register( 'SMW::SQLStore::AddCustomFixedPropertyTables', function( &$customFixedProperties, &$fixedPropertyTablePrefix ) {
+
+ // Standard table prefix
+ $customFixedProperties['Foo'] = '_Bar';
+
+ // Custom table prefix
+ $customFixedProperties['Foobar'] = '_Foooo';
+ $fixedPropertyTablePrefix['Foobar'] = 'smw_ext';
+
+ return true;
+ } );
+
+ $this->assertEquals(
+ 'smw_fpt_bar',
+ $store->findPropertyTableID( new \SMW\DIProperty( 'Foo' ) )
+ );
+
+ $this->assertEquals(
+ 'smw_ext_foooo',
+ $store->findPropertyTableID( new \SMW\DIProperty( 'Foobar' ) )
+ );
+ }
+
+ public function testRegisteredAfterDataUpdateComplete() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'is' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'is' )
+ ->with( $this->equalTo( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->setOption( 'smwgSemanticsEnabled', true );
+ $store->setOption( 'smwgAutoRefreshSubject', true );
+
+ $store->setLogger( $this->spyLogger );
+
+ $this->mwHooksHandler->register( 'SMW::SQLStore::AfterDataUpdateComplete', function( $store, $semanticData, $changeOp ) use ( $test ){
+ $test->is( $changeOp->getChangedEntityIdSummaryList() );
+
+ return true;
+ } );
+
+ $store->updateData(
+ new \SMW\SemanticData( DIWikiPage::newFromText( 'Foo' ) )
+ );
+ }
+
+ public function storeClassProvider() {
+
+ $provider[] = [ '\SMWSQLStore3' ];
+ $provider[] = [ '\SMW\SPARQLStore\SPARQLStore' ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SpecialAskTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SpecialAskTest.php
new file mode 100644
index 00000000..653aeaeb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/SpecialAskTest.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use DOMDocument;
+use SMW\MediaWiki\Specials\SpecialAsk;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author Stephan Gambke
+ */
+class SpecialAskTest extends \PHPUnit_Framework_TestCase {
+
+ private $oldRequestValues;
+ private $oldBodyText;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment(
+ [
+ 'smwgSpecialAskFormSubmitMethod' => SMW_SASK_SUBMIT_GET
+ ]
+ );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider provideTestData
+ * @param $params
+ */
+ public function testProducesWellformedHtml( $params ) {
+
+ $this->setupGlobals( $params );
+
+ $special = new SpecialAsk();
+ $special->execute( null );
+
+ $html = $GLOBALS['wgOut']->getHtml();
+ $html = '<!DOCTYPE html><html><body>' . $html . '</body></html>';
+
+ // Known tags DOMDocument has issues with
+ $html = str_replace( [ '<nowiki>', '</nowiki>' ], '', $html );
+
+ $document = new DOMDocument();
+
+ // https://stackoverflow.com/questions/6090667/php-domdocument-errors-warnings-on-html5-tags
+ libxml_use_internal_errors(true);
+ $result = $document->loadHTML( $html );
+ libxml_clear_errors();
+
+ $this->assertTrue( $result );
+
+ $result = $document->loadXML( $html );
+ $this->assertTrue( $result );
+
+ $this->restoreGlobals( $params );
+ }
+
+ /**
+ * @return array
+ */
+ public function provideTestData() {
+ return [
+ [ [ 'eq' => 'yes', 'q' => '' ] ],
+ [ [ 'eq' => 'no', 'q' => '[[]]' ] ],
+ ];
+ }
+
+ /**
+ * @param array $params
+ */
+ protected function setupGlobals( $params ) {
+ global $wgOut, $wgRequest;
+
+ $this->oldRequestValues = [];
+
+ foreach ( $params as $key => $value ) {
+
+ $oldVal = $wgRequest->getText( $key, null );
+ if ( $oldVal !== null ) {
+ $this->oldRequestValues[$key] = $oldVal;
+ }
+
+ $wgRequest->setVal( $key, $value );
+ }
+
+ $this->oldBodyText = $wgOut->getHTML();
+ $wgOut->clearHTML();
+ }
+
+ /**
+ * @param array $params
+ */
+ protected function restoreGlobals( $params ) {
+ global $wgOut, $wgRequest;
+
+ foreach ( $params as $key => $value ) {
+ if ( method_exists( $wgRequest, 'unsetVal' ) ) {
+ $wgRequest->unsetVal( $key );
+ } else {
+ $wgRequest->setVal( $key, null );
+ }
+ }
+ foreach ( $this->oldRequestValues as $key => $value ) {
+ $wgRequest->setVal( $key, $value );
+ }
+
+ $wgOut->clearHTML();
+ $wgOut->addHTML( $this->oldBodyText );
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nJsonFileIntegrityTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nJsonFileIntegrityTest.php
new file mode 100644
index 00000000..ba8163aa
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nJsonFileIntegrityTest.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\System;
+
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @group semantic-mediawiki
+ * @group system-test
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class I18nJsonFileIntegrityTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider mediawikiI18nFileProvider
+ */
+ public function testMediaWikiI18NJsonDecodeEncode( $file ) {
+
+ $jsonFileReader = UtilityFactory::getInstance()->newJsonFileReader( $file );
+
+ $this->assertInternalType(
+ 'integer',
+ $jsonFileReader->getModificationTime()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $jsonFileReader->read()
+ );
+ }
+
+ /**
+ * @dataProvider semanticMediaWikiI18nFileProvider
+ */
+ public function testSemanticMediaWikiI18NJsonDecodeEncode( $file ) {
+
+ $jsonFileReader = UtilityFactory::getInstance()->newJsonFileReader( $file );
+
+ $this->assertInternalType(
+ 'integer',
+ $jsonFileReader->getModificationTime()
+ );
+
+ $contents = $jsonFileReader->read();
+
+ $this->assertInternalType(
+ 'array',
+ $contents
+ );
+
+ $expectedKeys = [
+ 'fallback_language',
+ 'datatype' => [ 'labels', 'aliases' ],
+ 'property' => [ 'labels', 'aliases' ],
+ 'namespace' => [ 'labels', 'aliases' ],
+ 'date' => [ 'precision', 'format', 'months', 'days' ]
+ ];
+
+ // If the file is marked with isLanguageRedirect then only check for the fallbackLanguage
+ if ( isset( $contents['isLanguageRedirect'] ) && $contents['isLanguageRedirect'] ) {
+ return $this->assertArrayHasKey( 'fallback_language', $contents, $file );
+ }
+
+ foreach ( $expectedKeys as $key => $val ) {
+ if ( !is_array( $val ) ) {
+ $this->assertArrayHasKey( $val, $contents, "Failed on $file with key: $val" );
+ } else {
+ foreach ( $val as $k => $v ) {
+ $this->assertArrayHasKey( $v, $contents[$key], "Failed on $file with key: $key/$v" );
+ }
+ }
+ }
+ }
+
+ public function mediawikiI18nFileProvider() {
+ return $this->findFilesIn( $GLOBALS['wgMessagesDirs']['SemanticMediaWiki'] );
+ }
+
+ public function semanticMediaWikiI18nFileProvider() {
+ return $this->findFilesIn( $GLOBALS['smwgExtraneousLanguageFileDir'] );
+ }
+
+ private function findFilesIn( $location ) {
+
+ $provider = [];
+
+ $bulkFileProvider = UtilityFactory::getInstance()->newBulkFileProvider( $location );
+ $bulkFileProvider->searchByFileExtension( 'json' );
+
+ foreach ( $bulkFileProvider->getFiles() as $file ) {
+ $provider[] = [ $file ];
+ }
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nMsgKeyIntegrityTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nMsgKeyIntegrityTest.php
new file mode 100644
index 00000000..8804fd41
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/I18nMsgKeyIntegrityTest.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\System;
+
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @group semantic-mediawiki
+ * @group system-test
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class I18nMsgKeyIntegrityTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider mediawikiI18nFileProvider
+ */
+ public function testDecKiloSeparatorMsgKeySetting( $file ) {
+
+ $jsonFileReader = UtilityFactory::getInstance()->newJsonFileReader( $file );
+ $contents = $jsonFileReader->read();
+
+ $isComplete = true;
+
+ if ( isset( $contents['smw_decseparator'] ) ) {
+ $isComplete = isset( $contents['smw_kiloseparator'] );
+ }
+
+ if ( $isComplete && isset( $contents['smw_kiloseparator'] ) ) {
+ $isComplete = isset( $contents['smw_decseparator'] );
+ }
+
+ $this->assertTrue(
+ $isComplete,
+ 'Failed on ' . basename( $file ) . ' with an incomplete pair of smw_decseparator/smw_kiloseparator.'
+ );
+ }
+
+ /**
+ * @dataProvider mediawikiI18nFileProvider
+ */
+ public function testDecKiloSeparatorHasDifferentValue( $file ) {
+
+ $jsonFileReader = UtilityFactory::getInstance()->newJsonFileReader( $file );
+ $contents = $jsonFileReader->read();
+
+ $hasDifferentSeparatorValue = true;
+
+ // Test on whether the values are different, otherwise fail
+ if ( isset( $contents['smw_kiloseparator'] ) && isset( $contents['smw_decseparator'] ) ) {
+ $hasDifferentSeparatorValue = $contents['smw_kiloseparator'] != $contents['smw_decseparator'];
+ }
+
+ $this->assertTrue(
+ $hasDifferentSeparatorValue,
+ 'Failed on ' . basename( $file ) . ' where smw_decseparator/smw_kiloseparator have the same set of values.'
+ );
+ }
+
+ public function mediawikiI18nFileProvider() {
+ return $this->findFilesIn( $GLOBALS['wgMessagesDirs']['SemanticMediaWiki'] );
+ }
+
+ private function findFilesIn( $location ) {
+
+ $provider = [];
+
+ $bulkFileProvider = UtilityFactory::getInstance()->newBulkFileProvider( $location );
+ $bulkFileProvider->searchByFileExtension( 'json' );
+
+ foreach ( $bulkFileProvider->getFiles() as $id => $file ) {
+ $provider[$id] = [ $file ];
+ }
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/InstallationConfigurationIntegrityTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/InstallationConfigurationIntegrityTest.php
new file mode 100644
index 00000000..986d6419
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/InstallationConfigurationIntegrityTest.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace SMW\Tests\System;
+
+use SMW\ApplicationFactory;
+use SMW\Tests\Utils\GlobalsProvider;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-system
+ * @group mediawiki-databaseless
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class InstallationGlobalsProviderIntegrityTest extends \PHPUnit_Framework_TestCase {
+
+ private $globalsProvider;
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->globalsProvider = GlobalsProvider::getInstance();
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->globalsProvider->clear();
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testNamespaceSettingOnExampleIfSet() {
+
+ $expected = 'http://example.org/id/';
+
+ if ( $this->globalsProvider->get( 'smwgNamespace' ) !== $expected ) {
+ $this->markTestSkipped( "Skip test due to missing {$expected} setting" );
+ }
+
+ $this->assertSame(
+ $this->globalsProvider->get( 'smwgNamespace' ),
+ $this->applicationFactory->getSettings()->get( 'smwgNamespace' )
+ );
+ }
+
+ /**
+ * @dataProvider smwgNamespacesWithSemanticLinksProvider
+ */
+ public function testNamespacesWithSemanticLinksOnTravisCustomNamespace( $type, $container ) {
+
+ if ( !defined( 'NS_TRAVIS' ) ) {
+ $this->markTestSkipped( 'Test can only be executed with a specified NS_TRAVIS' );
+ }
+
+ $namespace = NS_TRAVIS;
+ $extraNamespaces = $this->globalsProvider->get( 'wgExtraNamespaces' );
+
+ $this->assertTrue(
+ isset( $extraNamespaces[$namespace] )
+ );
+
+ $foundNamespaceEntry = false;
+
+ foreach ( $container as $key => $value ) {
+ if ( $key === $namespace ) {
+ $foundNamespaceEntry = true;
+ break;
+ }
+ }
+
+ $this->assertTrue(
+ $foundNamespaceEntry,
+ "Asserts that smwgNamespacesWithSemanticLinks retrieved from {$type} contains the expected {$namespace} NS"
+ );
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function smwgNamespacesWithSemanticLinksProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ 'GLOBALS',
+ GlobalsProvider::getInstance()->get( 'smwgNamespacesWithSemanticLinks' )
+ ];
+
+ $provider[] = [
+ 'Settings',
+ ApplicationFactory::getInstance()->getSettings()->get( 'smwgNamespacesWithSemanticLinks' )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/LanguagesAccessibilityAndIntegrityTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/LanguagesAccessibilityAndIntegrityTest.php
new file mode 100644
index 00000000..ec8616c9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/LanguagesAccessibilityAndIntegrityTest.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace SMW\Tests\System;
+
+use SMW\Lang\Lang;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-system
+ * @group mediawiki-databaseless
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class LanguagesAccessibilityAndIntegrityTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider languageCodeProvider
+ */
+ public function testCommonInterfaceMethods( $langcode ) {
+
+ $methods = [
+ 'getDateFormats' => 'array',
+ 'getNamespaces' => 'array',
+ 'getNamespaceAliases' => 'array',
+ 'getDatatypeLabels' => 'array',
+ 'getDatatypeAliases' => 'array',
+ 'getPropertyLabels' => 'array',
+ 'getPropertyAliases' => 'array',
+ ];
+
+ $class = $this->loadLanguageFileAndConstructClass( $langcode );
+
+ foreach ( $methods as $method => $type ) {
+ $this->assertInternalType( $type, call_user_func( [ $class, $method ] ) );
+ }
+ }
+
+ /**
+ * @depends testCommonInterfaceMethods
+ * @dataProvider languageCodeProvider
+ */
+ public function testComparePredefinedPropertyLabels( $langcode ) {
+
+ $class = $this->loadLanguageFileAndConstructClass( $langcode );
+
+ $baseToCompareInstance = Lang::getInstance()->fetch( 'en' );
+ $targetLanguageInstance = $class;
+
+ $result = array_diff_key(
+ $baseToCompareInstance->getPropertyLabels(),
+ $targetLanguageInstance->getPropertyLabels()
+ );
+
+ $this->assertTrue(
+ $result === [],
+ "Asserts predfined property keys for the language pair EN - {$langcode} with {$this->formatAsString($result)}"
+ );
+ }
+
+ /**
+ * @dataProvider languageCodeProvider
+ */
+ public function testCompareMonthAndLabel( $langcode ) {
+
+ $class = $this->loadLanguageFileAndConstructClass( $langcode );
+
+ for ( $i=1; $i <= 12; $i++ ) {
+
+ $label = call_user_func( [ $class, 'getMonthLabel' ], $i );
+ $month = call_user_func( [ $class, 'findMonth' ], $label );
+
+ $this->assertInternalType( 'string', $label );
+ $this->assertEquals( $i, $month );
+ }
+ }
+
+ public function languageCodeProvider() {
+
+ $provider = [];
+
+ $languageCodes = [
+ 'En', 'Ar', 'Arz', 'Ca', 'De', 'Es', 'Fi',
+ 'Fr', 'He', 'Id', 'It', 'Nb', 'Nl', 'Pl',
+ 'Pt', 'Ru', 'Sk', 'Zh-cn', 'Zh-tw'
+ ];
+
+ foreach ( $languageCodes as $code ) {
+ $provider[] = [ $code ];
+ }
+
+ return $provider;
+ }
+
+ private function loadLanguageFileAndConstructClass( $langcode ) {
+ return Lang::getInstance()->fetch( $langcode );
+ }
+
+ private function formatAsString( $expected ) {
+ return is_array( $expected ) ? implode( ', ', $expected ) : $expected;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/ResourcesAccessibilityTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/ResourcesAccessibilityTest.php
new file mode 100644
index 00000000..19f6ffea
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/System/ResourcesAccessibilityTest.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SMW\Tests\System;
+
+use ResourceLoader;
+use ResourceLoaderContext;
+use ResourceLoaderModule;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ResourcesAccessibilityTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider moduleDataProvider
+ */
+ public function testModulesScriptsFilesAreAccessible( $modules, ResourceLoader $resourceLoader, $context ) {
+
+ foreach ( array_keys( $modules ) as $name ) {
+ $this->assertInternalType(
+ 'string',
+ $resourceLoader->getModule( $name )->getScript( $context )
+ );
+ }
+ }
+
+ /**
+ * @dataProvider moduleDataProvider
+ */
+ public function testModulesStylesFilesAreAccessible( $modules, ResourceLoader $resourceLoader, $context ) {
+
+ foreach ( array_keys( $modules ) as $name ) {
+
+ $styles = $resourceLoader->getModule( $name )->getStyles( $context );
+
+ foreach ( $styles as $style ) {
+ $this->assertInternalType( 'string', $style );
+ }
+ }
+ }
+
+ public function moduleDataProvider() {
+
+ $resourceLoader = new ResourceLoader();
+ $context = ResourceLoaderContext::newDummyContext();
+
+ foreach ( $GLOBALS['smwgResourceLoaderDefFiles'] as $key => $file ) {
+ $providers[] = [
+ include $file,
+ $resourceLoader,
+ $context
+ ];
+ }
+
+ return $providers;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/TempFileRoundTripTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/TempFileRoundTripTest.php
new file mode 100644
index 00000000..02b62475
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Integration/TempFileRoundTripTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace SMW\Tests\Integration;
+
+use SMW\Utils\TempFile;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TempFileRoundTripTest extends \PHPUnit_Framework_TestCase {
+
+ public function testRoundTrip() {
+
+ $expected = 'Test write file';
+ $tempFile = new TempFile();
+
+ $file = $tempFile->generate( 'Test' );
+
+ $tempFile->write( $file, $expected );
+
+ $this->assertTrue(
+ $tempFile->exists( $file )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $tempFile->read( $file, $tempFile->getCheckSum( $file ) )
+ );
+
+ $tempFile->write( $file, '++plus++', FILE_APPEND );
+
+ $this->assertEquals(
+ $expected . '++plus++',
+ $tempFile->read( $file )
+ );
+
+ $tempFile->delete( $file );
+
+ $this->assertFalse(
+ $tempFile->exists( $file )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseContentHandler.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseContentHandler.php
new file mode 100644
index 00000000..91b1debc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseContentHandler.php
@@ -0,0 +1,192 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Message;
+use SMW\Tests\Utils\File\ContentsReader;
+use SMW\Tests\Utils\File\LocalFileUpload;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Tests\Utils\PageDeleter;
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class JsonTestCaseContentHandler {
+
+ /**
+ * @var PageCreator
+ */
+ private $pageCreator;
+
+ /**
+ * @var PageDeleter
+ */
+ private $pageDeleter;
+
+ /**
+ * @var LocalFileUpload
+ */
+ private $LocalFileUpload;
+
+ /**
+ * @var array
+ */
+ private $pages = [];
+
+ /**
+ * @var string
+ */
+ private $skipOn = '';
+
+ /**
+ * @var string
+ */
+ private $testCaseLocation = '';
+
+ /**
+ * @since 2.5
+ *
+ * @param PageCreator $pageCreator
+ * @param PageDeleter $pageDeleter
+ * @param LocalFileUpload $localFileUpload
+ */
+ public function __construct( PageCreator $pageCreator, PageDeleter $pageDeleter, LocalFileUpload $localFileUpload ) {
+ $this->pageCreator = $pageCreator;
+ $this->pageDeleter = $pageDeleter;
+ $this->localFileUpload = $localFileUpload;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return array
+ */
+ public function getPages() {
+ return $this->pages;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $skipOn
+ */
+ public function skipOn( $skipOn ) {
+ $this->skipOn = $skipOn;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $testCaseLocation
+ */
+ public function setTestCaseLocation( $testCaseLocation ) {
+ $this->testCaseLocation = $testCaseLocation;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $pages
+ * @param integer $defaultNamespace
+ */
+ public function createPagesFrom( array $pages, $defaultNamespace = NS_MAIN ) {
+
+ foreach ( $pages as $page ) {
+
+ $skipOn = isset( $page['skip-on'] ) ? $page['skip-on'] : [];
+
+ if ( in_array( $this->skipOn, array_keys( $skipOn ) ) ) {
+ continue;
+ }
+
+ if ( ( !isset( $page['page'] ) && !isset( $page['name'] ) ) || !isset( $page['contents'] ) ) {
+ continue;
+ }
+
+ $namespace = isset( $page['namespace'] ) ? constant( $page['namespace'] ) : $defaultNamespace;
+
+ $this->createPage( $page, $namespace );
+ }
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $page
+ * @param integer $defaultNamespace
+ */
+ public function createPage( array $page, $namespace ) {
+
+ $pageContentLanguage = isset( $page['contentlanguage'] ) ? $page['contentlanguage'] : '';
+
+ if ( isset( $page['message-cache'] ) && $page['message-cache'] === 'clear' ) {
+ Message::clear();
+ }
+
+ $name = ( isset( $page['name'] ) ? $page['name'] : $page['page'] );
+
+ $title = Title::newFromText(
+ $name,
+ $namespace
+ );
+
+ if ( $namespace === NS_FILE && isset( $page['contents']['upload'] ) ) {
+ return $this->doUploadFile( $title, $page['contents']['upload'] );
+ }
+
+ if ( is_array( $page['contents'] ) && isset( $page['contents']['import-from'] ) ) {
+ $contents = ContentsReader::readContentsFrom(
+ $this->testCaseLocation . $page['contents']['import-from']
+ );
+ } else {
+ $contents = $page['contents'];
+ }
+
+ $this->pageCreator->createPage( $title, $contents, $pageContentLanguage );
+
+ $this->pages[] = $this->pageCreator->getPage();
+
+ if ( isset( $page['move-to'] ) ) {
+ $this->doMovePage( $page, $namespace );
+ }
+
+ if ( isset( $page['do-purge'] ) ) {
+ $this->pageCreator->getPage()->doPurge();
+ }
+
+ if ( isset( $page['do-delete'] ) && $page['do-delete'] ) {
+ $this->pageDeleter->deletePage( $title );
+ }
+ }
+
+ private function doMovePage( $page, $namespace ) {
+ $target = Title::newFromText(
+ $page['move-to']['target'],
+ $namespace
+ );
+
+ $this->pageCreator->doMoveTo(
+ $target,
+ $page['move-to']['is-redirect']
+ );
+
+ $this->pages[] = $target;
+ }
+
+ private function doUploadFile( $title, array $contents ) {
+
+ $this->localFileUpload->doUploadCopyFromLocation(
+ $this->testCaseLocation . $contents['file'],
+ $title->getText(),
+ $contents['text']
+ );
+
+ TestEnvironment::executePendingDeferredUpdates();
+ $this->pages[] = $title;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseFileHandler.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseFileHandler.php
new file mode 100644
index 00000000..052dee98
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseFileHandler.php
@@ -0,0 +1,466 @@
+<?php
+
+namespace SMW\Tests;
+
+use RuntimeException;
+use SMW\Tests\Utils\File\JsonFileReader;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class JsonTestCaseFileHandler {
+
+ /**
+ * @var JsonFileReader
+ */
+ private $fileReader;
+
+ /**
+ * @var string
+ */
+ private $reasonToSkip = '';
+
+ /**
+ * @since 2.2
+ *
+ * @param JsonFileReader $fileReader
+ */
+ public function __construct( JsonFileReader $fileReader ) {
+ $this->fileReader = $fileReader;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return boolean
+ */
+ public function isIncomplete() {
+
+ $meta = $this->getFileContentsFor( 'meta' );
+ $isIncomplete = isset( $meta['is-incomplete'] ) ? (bool)$meta['is-incomplete'] : false;
+
+ if ( $isIncomplete ) {
+ $this->reasonToSkip = '"'. $this->getFileContentsFor( 'description' ) . '" has been marked as incomplete.';
+ }
+
+ return $isIncomplete;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return boolean
+ */
+ public function getDebugMode() {
+
+ $meta = $this->getFileContentsFor( 'meta' );
+
+ return isset( $meta['debug'] ) ? (bool)$meta['debug'] : false;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @return boolean
+ */
+ public function hasAllRequirements( $dependencyDef = [] ) {
+
+ $requires = $this->getContentsFor( 'requires' );
+
+ if ( $requires === [] ) {
+ return true;
+ }
+
+ foreach ( $requires as $key => $value ) {
+ $res = false;
+
+ if ( isset( $dependencyDef[$key] ) && is_callable( $dependencyDef[$key] ) ) {
+ $res = call_user_func_array( $dependencyDef[$key], [ $value, &$this->reasonToSkip ] );
+ }
+
+ if ( $res === false ) {
+
+ // Default msg!
+ if ( $this->reasonToSkip === '' ) {
+ $this->reasonToSkip = "$key requirements were not met!";
+ }
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param array $case
+ * @param string $identifier
+ *
+ * @return boolean
+ */
+ public function requiredToSkipFor( array $case, $identifier ) {
+
+ $skipOn = isset( $case['skip-on'] ) ? $case['skip-on'] : [];
+ $identifier = strtolower( $identifier );
+
+ $version = $GLOBALS['wgVersion'];
+
+ foreach ( $skipOn as $id => $value ) {
+
+ $versionToSkip = '';
+ $compare = '=';
+ $noop = '';
+
+ if ( is_array( $value ) ) {
+ $versionToSkip = $value[0];
+ $reason = $value[1];
+ } else {
+ $reason = $value;
+ }
+
+ // Suppor for { "skip-on": { "foo": [ "not", "Exclude all except foo ..." ] }
+ if ( $versionToSkip === 'not' && $identifier === $id ) {
+ continue;
+ } elseif ( $versionToSkip === 'not' && $identifier !== $id ) {
+ return true;
+ }
+
+ // Suppor for { "skip-on": { "virtuoso": "Virtuoso 6.1 ..." }
+ if ( $identifier === $id ) {
+ return true;
+ }
+
+ // Suppor for { "skip-on": { "smw->2.5.x": "Reason is ..." }
+ // or { "skip-on": { "mw->1.30.x": "Reason is ..." }
+ if ( strpos( $id, 'mw-' ) !== false ) {
+ list( $noop, $versionToSkip ) = explode( "mw-", $id, 2 );
+ }
+
+ if ( strpos( $id, 'hhvm-' ) !== false ) {
+ list( $noop, $versionToSkip ) = explode( "hhvm-", $id, 2 );
+ }
+
+ // Suppor for { "skip-on": { "mediawiki": [ ">1.29.x", "Reason is ..." ] }
+ if ( strpos( $id, 'smw' ) !== false ) {
+ $version = SMW_VERSION;
+ } elseif ( strpos( $id, 'mediawiki' ) !== false || strpos( $id, 'mw' ) !== false ) {
+ $version = $GLOBALS['wgVersion'];
+ } elseif ( strpos( $id, 'hhvm' ) !== false ) {
+ $version = defined( 'HHVM_VERSION' ) ? HHVM_VERSION : 0;
+ } elseif ( strpos( $id, 'php' ) !== false ) {
+ $version = defined( 'PHP_VERSION' ) ? PHP_VERSION : 0;
+ }
+
+ if ( $versionToSkip !== '' && ( $versionToSkip{0} === '<' || $versionToSkip{0} === '>' ) ) {
+ $compare = $versionToSkip{0};
+ $versionToSkip = substr( $versionToSkip, 1 );
+ }
+
+ if ( strpos( $versionToSkip, '.x' ) ) {
+ $versionToSkip = str_replace( '.x', '.9999', $versionToSkip );
+ $compare = $compare === '=' ? '<' : $compare;
+ }
+
+ if ( strpos( $versionToSkip, '<' ) ) {
+ $versionToSkip = str_replace( '<', '', $versionToSkip );
+ $compare = '<';
+ }
+
+ // Skip any version as in { "skip-on": { "mediawiki": [ "*", "Reason is ..." ] }
+ if ( $versionToSkip === '*' ) {
+ return true;
+ }
+
+ if ( version_compare( $version, $versionToSkip, $compare ) ) {
+ $this->reasonToSkip = "$version version is not supported ({$reason})";
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return boolean
+ */
+ public function requiredToSkipForConnector( $connectorId ) {
+
+ $connectorId = strtolower( $connectorId );
+ $meta = $this->getFileContentsFor( 'meta' );
+
+ $skipOn = isset( $meta['skip-on'] ) ? $meta['skip-on'] : [];
+
+ if ( in_array( $connectorId, array_keys( $skipOn ) ) ) {
+ $this->reasonToSkip = $skipOn[$connectorId];
+ }
+
+ return $this->reasonToSkip !== '';
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return boolean
+ */
+ public function requiredToSkipForJsonVersion( $version ) {
+
+ $meta = $this->getFileContentsFor( 'meta' );
+
+ if ( version_compare( $version, $meta['version'], 'ne' ) ) {
+ $this->reasonToSkip = $meta['version'] . " is not supported due to a required {$version} test case version.";
+ }
+
+ return $this->reasonToSkip !== '';
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return boolean
+ */
+ public function requiredToSkipForMwVersion( $mwVersion ) {
+
+ $meta = $this->getFileContentsFor( 'meta' );
+ $skipOn = isset( $meta['skip-on'] ) ? $meta['skip-on'] : [];
+
+ foreach ( $skipOn as $id => $reason ) {
+
+ if ( strpos( $id, 'mw-' ) === false ) {
+ continue;
+ }
+
+ list( $mw, $versionToSkip ) = explode( "mw-", $id, 2 );
+ $compare = '=';
+
+ if ( strpos( $versionToSkip, '.x' ) ) {
+ $versionToSkip = str_replace( '.x', '.9999', $versionToSkip );
+ $compare = '<';
+ }
+
+ if ( strpos( $versionToSkip, '<' ) ) {
+ $versionToSkip = str_replace( '<', '', $versionToSkip );
+ $compare = '<';
+ }
+
+ if ( version_compare( $mwVersion, $versionToSkip, $compare ) ) {
+ $this->reasonToSkip = "MediaWiki " . $mwVersion . " version is not supported ({$reason})";
+ break;
+ }
+ }
+
+ return $this->reasonToSkip !== '';
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return string
+ */
+ public function getReasonForSkip() {
+ return $this->reasonToSkip;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $key
+ *
+ * @return booleam
+ */
+ public function hasSetting( $key ) {
+
+ $settings = $this->getFileContentsFor( 'settings' );
+
+ return isset( $settings[$key] );
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return array|integer|string|boolean
+ * @throws RuntimeException
+ */
+ public function getSettingsFor( $key, $callback = null ) {
+
+ $settings = $this->getFileContentsFor( 'settings' );
+
+ if ( isset( $settings[$key] ) && is_callable( $callback ) ) {
+ return call_user_func_array( $callback, [ $settings[$key] ] );
+ }
+
+ // Needs special attention due to NS constant usage
+ if ( $key === 'smwgNamespacesWithSemanticLinks' && isset( $settings[$key] ) ) {
+ $smwgNamespacesWithSemanticLinks = [];
+
+ foreach ( $settings[$key] as $ns => $value ) {
+ $smwgNamespacesWithSemanticLinks[constant( $ns )] = (bool)$value;
+ }
+
+ return $smwgNamespacesWithSemanticLinks;
+ }
+
+ $constantFeaturesList = [
+ 'smwgSparqlQFeatures',
+ 'smwgDVFeatures',
+ 'smwgFulltextSearchIndexableDataTypes',
+ 'smwgFieldTypeFeatures',
+ 'smwgQueryProfiler',
+ 'smwgParserFeatures',
+ 'smwgCategoryFeatures',
+ 'smwgQSortFeatures'
+ ];
+
+ foreach ( $constantFeaturesList as $constantFeatures ) {
+ if ( $key === $constantFeatures && isset( $settings[$key] ) ) {
+ $features = '';
+
+ if ( !is_array( $settings[$key] ) ) {
+ return $settings[$key];
+ }
+
+ foreach ( $settings[$key] as $value ) {
+ $features = constant( $value ) | (int)$features;
+ }
+
+ return $features;
+ }
+ }
+
+ if ( $key === 'wgDefaultUserOptions' && isset( $settings[$key] ) ) {
+ return array_merge( $GLOBALS['wgDefaultUserOptions'], $settings[$key] );
+ }
+
+ // Needs special attention due to constant usage
+ if ( $key === 'smwgQConceptCaching' && isset( $settings[$key] ) ) {
+ return constant( $settings[$key] );
+ }
+
+ // Needs special attention due to constant usage
+ if ( strpos( $key, 'CacheType' ) !== false && isset( $settings[$key] ) ) {
+ return $settings[$key] === false ? CACHE_NONE : defined( $settings[$key] ) ? constant( $settings[$key] ) : $settings[$key];
+ }
+
+ if ( isset( $settings[$key] ) ) {
+ return $settings[$key];
+ }
+
+ // Return values from the global settings as default
+ if ( isset( $GLOBALS[$key] ) || array_key_exists( $key, $GLOBALS ) ) {
+ return $GLOBALS[$key];
+ }
+
+ // Key is unknown, TestConfig will remove any remains during tearDown
+ return null;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return array
+ */
+ public function getListOfProperties() {
+ return $this->getFileContentsFor( 'properties' );
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return array
+ */
+ public function getListOfSubjects() {
+ return $this->getFileContentsFor( 'subjects' );
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return array
+ */
+ public function getPageCreationSetupList() {
+ return $this->getContentsFor( 'setup' );
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param string $key
+ *
+ * @return array
+ */
+ public function getContentsFor( $key ) {
+
+ try{
+ $contents = $this->getFileContentsFor( $key );
+ } catch( \Exception $e ) {
+ $contents = [];
+ }
+
+ return $contents;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param string $key
+ *
+ * @return array
+ */
+ public function findTestCasesFor( $key ) {
+ return $this->getContentsFor( $key );
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+ public function findTasksBeforeTestExecutionByType( $type ) {
+ $contents = $this->getContentsFor( 'beforeTest' );
+ return isset( $contents[$type] ) ? $contents[$type] : [];
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $type
+ *
+ * @return array
+ */
+ public function findTestCasesByType( $type ) {
+ return array_filter( $this->getContentsFor( 'tests' ), function( $contents ) use( $type ) {
+ return isset( $contents['type'] ) && $contents['type'] === $type;
+ } );
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $type
+ *
+ * @return integer
+ */
+ public function countTestCasesByType( $type ) {
+ return count( $this->findTestCasesByType( $type ) );
+ }
+
+ private function getFileContentsFor( $index ) {
+
+ $contents = $this->fileReader->read();
+
+ if ( isset( $contents[$index] ) ) {
+ return $contents[$index];
+ }
+
+ throw new RuntimeException( "{$index} is unknown" );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseScriptRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseScriptRunner.php
new file mode 100644
index 00000000..1fb8d779
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/JsonTestCaseScriptRunner.php
@@ -0,0 +1,322 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * The JsonTestCaseScriptRunner is a convenience provider for `Json` formatted
+ * integration tests to allow writing tests quicker without the need to setup
+ * or tear down specific data structures.
+ *
+ * The JSON format should make it also possible for novice user to understand
+ * what sort of tests are run as the content is based on wikitext rather than
+ * native PHP.
+ *
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+abstract class JsonTestCaseScriptRunner extends MwDBaseUnitTestCase {
+
+ /**
+ * @var FileReader
+ */
+ private $fileReader;
+
+ /**
+ * @var JsonTestCaseFileHandler
+ */
+ private $jsonTestCaseFileHandler;
+
+ /**
+ * @var JsonTestCaseContentHandler
+ */
+ private $jsonTestCaseContentHandler;
+
+ /**
+ * @var array
+ */
+ private $itemsMarkedForDeletion = [];
+
+ /**
+ * @var array
+ */
+ private $configValueCallback = [];
+
+ /**
+ * @var boolean
+ */
+ protected $deletePagesOnTearDown = true;
+
+ /**
+ * @var string
+ */
+ protected $searchByFileExtension = 'json';
+
+ /**
+ * @var string
+ */
+ protected $connectorId = '';
+
+ protected function setUp() {
+ parent::setUp();
+
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+ $utilityFactory->newMwHooksHandler()->deregisterListedHooks();
+ $utilityFactory->newMwHooksHandler()->invokeHooksFromRegistry();
+
+ $this->fileReader = $utilityFactory->newJsonFileReader();
+
+ $this->jsonTestCaseContentHandler = new JsonTestCaseContentHandler(
+ $utilityFactory->newPageCreator(),
+ $utilityFactory->newPageDeleter(),
+ $utilityFactory->newLocalFileUpload()
+ );
+
+ if ( $this->getStore() instanceof \SMWSparqlStore ) {
+ $this->connectorId = strtolower( $GLOBALS['smwgSparqlRepositoryConnector'] );
+ } elseif ( $this->getStore() instanceof \SMW\Elastic\ElasticStore ) {
+ $this->connectorId = 'elastic';
+ } else {
+ $this->connectorId = strtolower( $this->getDBConnection()->getType() );
+ }
+ }
+
+ protected function tearDown() {
+
+ if ( $this->deletePagesOnTearDown ) {
+ $this->testEnvironment->flushPages( $this->itemsMarkedForDeletion );
+ }
+
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @return string
+ */
+ abstract protected function getTestCaseLocation();
+
+ /**
+ * @param JsonTestCaseFileHandler $jsonTestCaseFileHandler
+ */
+ abstract protected function runTestCaseFile( JsonTestCaseFileHandler $jsonTestCaseFileHandler );
+
+ /**
+ * @return string
+ */
+ protected function getRequiredJsonTestCaseMinVersion() {
+ return '0.1';
+ }
+
+ /**
+ * @return array
+ */
+ protected function getAllowedTestCaseFiles() {
+ return [];
+ }
+
+ /**
+ * Selected list of settings (internal or MediaWiki related) that are
+ * permissible for the time of the test run to be manipulated.
+ *
+ * For a configuration that requires special treatment (i.e. where a simple
+ * assignment isn't sufficient), a callback can be assigned to a settings
+ * key in order to sort out required manipulation (constants etc.).
+ *
+ * @return array
+ */
+ protected function getPermittedSettings() {
+
+ // Ensure that the context is set for a selected language
+ // and dependent objects are reset
+ $this->registerConfigValueCallback( 'wgContLang', function( $val ) {
+ \RequestContext::getMain()->setLanguage( $val );
+ \SMW\Localizer::getInstance()->clear();
+ $lang = \Language::factory( $val );
+
+ // https://github.com/wikimedia/mediawiki/commit/49ce67be93dfbb40d036703dad2278ea9843f1ad
+ $this->testEnvironment->redefineMediaWikiService( 'ContentLanguage', function () use ( $lang ) {
+ return $lang;
+ } );
+
+ return $lang;
+ } );
+
+ $this->registerConfigValueCallback( 'wgLang', function( $val ) {
+ \RequestContext::getMain()->setLanguage( $val );
+ \SMW\Localizer::getInstance()->clear();
+ return \Language::factory( $val );
+ } );
+
+ return [];
+ }
+
+ /**
+ * @param string $key
+ * @param Closure $callback
+ */
+ protected function registerConfigValueCallback( $key, \Closure $callback ) {
+ $this->configValueCallback[$key] = $callback;
+ }
+
+ /**
+ * @return callable|null
+ */
+ protected function getConfigValueCallback( $key ) {
+ return isset( $this->configValueCallback[$key] ) ? $this->configValueCallback[$key] : null;
+ }
+
+ /**
+ * Normally returns TRUE but can act on the list retrieved from
+ * JsonTestCaseScriptRunner::getAllowedTestCaseFiles (or hereof) to filter
+ * selected files and help fine tune a setup or debug a potential issue
+ * without having to run all test files at once.
+ *
+ * @param string $file
+ *
+ * @return boolean
+ */
+ protected function canTestCaseFile( $file ) {
+
+ // Filter specific files on-the-fly
+ $allowedTestCaseFiles = $this->getAllowedTestCaseFiles();
+
+ if ( $allowedTestCaseFiles === [] ) {
+ return true;
+ }
+
+ // Doesn't require the exact name
+ foreach ( $allowedTestCaseFiles as $fileName ) {
+ if ( strpos( $file, $fileName ) !== false ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @dataProvider jsonFileProvider
+ */
+ public function testCaseFile( $file ) {
+
+ if ( !$this->canTestCaseFile( $file ) ) {
+ $this->markTestSkipped( $file . ' excluded from the test run' );
+ }
+
+ $this->fileReader->setFile( $file );
+ $this->runTestCaseFile( new JsonTestCaseFileHandler( $this->fileReader ) );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonFileProvider() {
+
+ $provider = [];
+
+ $bulkFileProvider = UtilityFactory::getInstance()->newBulkFileProvider(
+ $this->getTestCaseLocation()
+ );
+
+ $bulkFileProvider->searchByFileExtension( $this->searchByFileExtension );
+
+ foreach ( $bulkFileProvider->getFiles() as $file ) {
+ $provider[basename( $file )] = [ $file ];
+ }
+
+ return $provider;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param mixed $key
+ * @param mixed $value
+ */
+ protected function changeGlobalSettingTo( $key, $value ) {
+ $this->testEnvironment->addConfiguration( $key, $value );
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @return []
+ */
+ protected function getDependencyDefinitions() {
+ return [];
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param JsonTestCaseFileHandler $jsonTestCaseFileHandler
+ */
+ protected function checkEnvironmentToSkipCurrentTest( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
+
+ if ( $jsonTestCaseFileHandler->isIncomplete() ) {
+ $this->markTestIncomplete( $jsonTestCaseFileHandler->getReasonForSkip() );
+ }
+
+ if ( !$jsonTestCaseFileHandler->hasAllRequirements( $this->getDependencyDefinitions() ) ) {
+ $this->markTestSkipped( $jsonTestCaseFileHandler->getReasonForSkip() );
+ }
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipForJsonVersion( $this->getRequiredJsonTestCaseMinVersion() ) ) {
+ $this->markTestSkipped( $jsonTestCaseFileHandler->getReasonForSkip() );
+ }
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipForMwVersion( $GLOBALS['wgVersion'] ) ) {
+ $this->markTestSkipped( $jsonTestCaseFileHandler->getReasonForSkip() );
+ }
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipForConnector( $this->getDBConnection()->getType() ) ) {
+ $this->markTestSkipped( $jsonTestCaseFileHandler->getReasonForSkip() );
+ }
+
+ if ( $jsonTestCaseFileHandler->requiredToSkipForConnector( $this->connectorId ) ) {
+ $this->markTestSkipped( $jsonTestCaseFileHandler->getReasonForSkip() );
+ }
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $pages
+ * @param integer $defaultNamespace
+ */
+ protected function createPagesFrom( array $pages, $defaultNamespace = NS_MAIN ) {
+
+ $this->jsonTestCaseContentHandler->skipOn(
+ $this->connectorId
+ );
+
+ $this->jsonTestCaseContentHandler->setTestCaseLocation(
+ $this->getTestCaseLocation()
+ );
+
+ $this->jsonTestCaseContentHandler->createPagesFrom(
+ $pages,
+ $defaultNamespace
+ );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->itemsMarkedForDeletion = $this->jsonTestCaseContentHandler->getPages();
+ }
+
+ /**
+ * @deprecated 2.5
+ */
+ protected function createPagesFor( array $pages, $defaultNamespace ) {
+ $this->createPagesFrom( $pages, $defaultNamespace );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/PHPUnitCompat.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/PHPUnitCompat.php
new file mode 100644
index 00000000..0ce51bd9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/PHPUnitCompat.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+trait PHPUnitCompat {
+
+ /**
+ * @see PHPUnit_Framework_TestCase::setExpectedException
+ */
+ public function setExpectedException( $name, $message = '', $code = null ) {
+ if ( is_callable( [ $this, 'expectException' ] ) ) {
+ if ( $name !== null ) {
+ $this->expectException( $name );
+ }
+ if ( $message !== '' ) {
+ $this->expectExceptionMessage( $message );
+ }
+ if ( $code !== null ) {
+ $this->expectExceptionCode( $code );
+ }
+ } else {
+ parent::setExpectedException( $name, $message, $code );
+ }
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterRegistryTestCase.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterRegistryTestCase.php
new file mode 100644
index 00000000..574faeb2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterRegistryTestCase.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Test;
+
+/**
+ * Base class for SMW\ResultPrinter tests.
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @codeCoverageIgnore
+ *
+ * @license GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+abstract class QueryPrinterRegistryTestCase extends QueryPrinterTestCase {
+
+ /**
+ * Returns the names of the formats supported by the
+ * \SMW\ResultPrinter being tested.
+ *
+ * @since 1.8
+ *
+ * @return array
+ */
+ public abstract function getFormats();
+
+ /**
+ * @since 1.8
+ *
+ * @return array
+ */
+ public function constructorProvider() {
+ $argumentLists = [];
+
+ foreach ( $this->getFormats() as $format ) {
+ $argumentLists[] = [ $format, true ];
+ $argumentLists[] = [ $format, false ];
+ }
+
+ return $argumentLists;
+ }
+
+ /**
+ * Creates and returns a new instance of the result printer.
+ *
+ * @since 1.8
+ *
+ * @param string $format
+ * @param boolean $isInline
+ *
+ * @return \SMW\ResultPrinter
+ */
+ protected function newInstance( $format, $isInline ) {
+ $class = $this->getClass();
+ return new $class( $format, $isInline );
+ }
+
+ /**
+ * @since 1.8
+ * @return array
+ */
+ public function instanceProvider() {
+ $phpFails = [ $this, 'newInstance' ];
+
+ return array_map(
+ function( array $args ) use ( $phpFails ) {
+ return call_user_func_array( $phpFails, $args );
+ },
+ $this->constructorProvider()
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ *
+ * @since 1.8
+ *
+ * @param string $format
+ * @param boolean $isInline
+ */
+ public function testConstructor( $format, $isInline ) {
+ $instance = $this->newInstance( $format, $isInline );
+
+ $this->assertInstanceOf( '\SMW\ResultPrinter', $instance );
+ }
+}
+
+/**
+ * SMWResultPrinter
+ *
+ * @deprecated since SMW 1.9
+ */
+class_alias( 'SMW\Test\QueryPrinterRegistryTestCase', 'SMW\Test\ResultPrinterTestCase' );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterTestCase.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterTestCase.php
new file mode 100644
index 00000000..69e46ad3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/QueryPrinterTestCase.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Test;
+
+use ReflectionClass;
+use SMW\ResultPrinter;
+
+/**
+ * Class contains methods to access data in connection with the QueryPrinter
+ *
+ * @since 1.9
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * Class contains methods to access data in connection with the QueryPrinter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+abstract class QueryPrinterTestCase extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * Helper method sets result printer parameters
+ *
+ * @param ResultPrinter $instance
+ * @param array $parameters
+ *
+ * @return ResultPrinter
+ */
+ protected function setParameters( ResultPrinter $instance, array $parameters ) {
+
+ $reflector = new ReflectionClass( $this->getClass() );
+ $params = $reflector->getProperty( 'params' );
+ $params->setAccessible( true );
+ $params->setValue( $instance, $parameters );
+
+ if ( isset( $parameters['searchlabel'] ) ) {
+ $searchlabel = $reflector->getProperty( 'mSearchlabel' );
+ $searchlabel->setAccessible( true );
+ $searchlabel->setValue( $instance, $parameters['searchlabel'] );
+ }
+
+ if ( isset( $parameters['headers'] ) ) {
+ $searchlabel = $reflector->getProperty( 'mShowHeaders' );
+ $searchlabel->setAccessible( true );
+ $searchlabel->setValue( $instance, $parameters['headers'] );
+ }
+
+ return $instance;
+
+ }
+
+ protected function arrayWrap( array $elements ) {
+ return array_map(
+ function ( $element ) {
+ return [ $element ];
+ },
+ $elements
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SemanticMediaWikiTestCase.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SemanticMediaWikiTestCase.php
new file mode 100644
index 00000000..2a480dd1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SemanticMediaWikiTestCase.php
@@ -0,0 +1,260 @@
+<?php
+
+namespace SMW\Test;
+
+use FauxRequest;
+use Language;
+use ReflectionClass;
+use RequestContext;
+use SMW\DependencyContainer;
+use SMW\DIWikiPage;
+use SMW\Settings;
+use SMW\SimpleDependencyBuilder;
+use SMW\StoreFactory;
+use SMW\Tests\Utils\Mock\CoreMockObjectRepository;
+use SMW\Tests\Utils\Mock\MediaWikiMockObjectRepository;
+use SMW\Tests\Utils\Mock\MockObjectBuilder;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use Title;
+use WebRequest;
+
+/**
+ * @codeCoverageIgnore
+ *
+ * Class contains general purpose methods
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+abstract class SemanticMediaWikiTestCase extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * Returns the name of the deriving class being tested
+ *
+ * @since 1.9
+ *
+ * @return string
+ */
+ public abstract function getClass();
+
+ /**
+ * Helper method that returns a MockObjectBuilder object
+ *
+ * @since 1.9
+ *
+ * @return MockObjectBuilder
+ */
+ public function newMockBuilder() {
+
+ $builder = new MockObjectBuilder();
+ $builder->registerRepository( new CoreMockObjectRepository() );
+ $builder->registerRepository( new MediaWikiMockObjectRepository() );
+
+ return $builder;
+ }
+
+ /**
+ * Helper method that returns a SimpleDependencyBuilder object
+ *
+ * @since 1.9
+ *
+ * @param DependencyContainer $dependencyContainer
+ *
+ * @return SimpleDependencyBuilder
+ */
+ public function newDependencyBuilder( DependencyContainer $dependencyContainer = null ) {
+ return new SimpleDependencyBuilder( $dependencyContainer );
+ }
+
+ /**
+ * Helper method that returns a ReflectionClass object
+ *
+ * @since 1.9
+ *
+ * @param string|null $class
+ *
+ * @return ReflectionClass
+ */
+ public function newReflector( $class = null ) {
+ return new ReflectionClass( $class === null ? $this->getClass() : $class );
+ }
+
+ /**
+ * Helper method that returns a randomized Title object to avoid results
+ * are influenced by cross instantiated objects with the same title name
+ *
+ * @since 1.9
+ *
+ * @param $namespace
+ * @param $text|null
+ *
+ * @return Title
+ */
+ protected function newTitle( $namespace = NS_MAIN, $text = null ) {
+ return Title::newFromText( $text === null ? $this->newRandomString() : $text, $namespace );
+ }
+
+ /**
+ * Helper method that returns a User object
+ *
+ * @since 1.9
+ *
+ * @return User
+ */
+ protected function getUser() {
+ return $this->newMockUser();
+ }
+
+ /**
+ * Helper method that returns a User object
+ *
+ * @since 1.9
+ *
+ * @return User
+ */
+ protected function newMockUser() {
+ return new MockSuperUser();
+ }
+
+ /**
+ * Helper method that returns a Language object
+ *
+ * @since 1.9
+ *
+ * @return Language
+ */
+ protected function getLanguage( $langCode = 'en' ) {
+ return Language::factory( $langCode );
+ }
+
+ /**
+ * Returns RequestContext object
+ *
+ * @param array $params
+ *
+ * @return RequestContext
+ */
+ protected function newContext( $request = [] ) {
+
+ $context = new RequestContext();
+
+ if ( $request instanceof WebRequest ) {
+ $context->setRequest( $request );
+ } else {
+ $context->setRequest( new FauxRequest( $request, true ) );
+ }
+
+ $context->setUser( new MockSuperUser() );
+
+ return $context;
+ }
+
+ /**
+ * Helper method that returns a randomized DIWikiPage object
+ *
+ * @since 1.9
+ *
+ * @param $namespace
+ *
+ * @return DIWikiPage
+ */
+ protected function getSubject( $namespace = NS_MAIN ) {
+ return DIWikiPage::newFromTitle( $this->newTitle( $namespace ) );
+ }
+
+ /**
+ * Helper method that returns a DIWikiPage object
+ *
+ * @since 1.9
+ *
+ * @param Title|null $title
+ *
+ * @return DIWikiPage
+ */
+ protected function newSubject( Title $title = null ) {
+ return DIWikiPage::newFromTitle( $title === null ? $this->newTitle() : $title );
+ }
+
+ /**
+ * Helper method that returns a Settings object
+ *
+ * @since 1.9
+ *
+ * @param array $settings
+ *
+ * @return Settings
+ */
+ protected function newSettings( array $settings = [] ) {
+ return Settings::newFromArray( $settings );
+ }
+
+ /**
+ * Helper method that returns a random string
+ *
+ * @since 1.9
+ *
+ * @param $length
+ * @param $prefix identify a specific random string during testing
+ *
+ * @return string
+ */
+ protected function newRandomString( $length = 10, $prefix = null ) {
+ return $prefix . ( $prefix ? '-' : '' ) . substr( str_shuffle( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, $length );
+ }
+
+ /**
+ * Helper method to skip the test if it is not a SQLStore
+ *
+ * @since 1.9
+ */
+ protected function runOnlyOnSQLStore( $store = null ) {
+
+ if ( $store === null ) {
+ $store = StoreFactory::getStore();
+ }
+
+ if ( !( $store instanceof \SMWSQLStore3 ) ) {
+ $this->markTestSkipped( 'Test only applicable to SMWSQLStore3' );
+ }
+
+ }
+
+ protected function getStore() {
+ $store = StoreFactory::getStore();
+
+ if ( !( $store instanceof \SMWSQLStore3 ) ) {
+ $this->markTestSkipped( 'Test only applicable for SMWSQLStore3' );
+ }
+
+ return $store;
+ }
+
+ /**
+ * Utility method taking an array of elements and wrapping
+ * each element in it's own array. Useful for data providers
+ * that only return a single argument.
+ *
+ * @see MediaWikiTestCase::arrayWrap
+ *
+ * @since 1.9
+ *
+ * @param array $elements
+ *
+ * @return array
+ */
+ protected function arrayWrap( array $elements ) {
+ return array_map(
+ function ( $element ) {
+ return [ $element ];
+ },
+ $elements
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SpecialPageTestCase.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SpecialPageTestCase.php
new file mode 100644
index 00000000..ecc8cebc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/SpecialPageTestCase.php
@@ -0,0 +1,146 @@
+<?php
+
+namespace SMW\Test;
+
+use FauxRequest;
+use Language;
+use OutputPage;
+use RequestContext;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use SpecialPage;
+use WebRequest;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group medium
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9.0.2
+ *
+ * @author mwjames
+ */
+abstract class SpecialPageTestCase extends \PHPUnit_Framework_TestCase {
+
+ protected $obLevel;
+ protected $store = null;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->obLevel = ob_get_level();
+ }
+
+ protected function tearDown() {
+
+ $obLevel = ob_get_level();
+
+ while ( ob_get_level() > $this->obLevel ) {
+ ob_end_clean();
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * @return SpecialPage
+ */
+ protected abstract function getInstance();
+
+ protected function setStore( $store ) {
+ $this->store = $store;
+ }
+
+ /**
+ * Borrowed from \Wikibase\Test\SpecialPageTestBase
+ *
+ * @param string $sub The subpage parameter to call the page with
+ * @param WebRequest $request Web request that may contain URL parameters, etc
+ */
+ protected function execute( $sub = '', WebRequest $request = null, $user = null ) {
+
+ $request = $request === null ? new FauxRequest() : $request;
+ $response = $request->response();
+
+ $page = $this->getInstance();
+
+ if ( $this->store !== null ) {
+ $page->setStore( $this->store );
+ }
+
+ $page->setContext( $this->makeRequestContext(
+ $request,
+ $user,
+ $this->getTitle( $page )
+ ) );
+
+ $out = $page->getOutput();
+
+ ob_start();
+ $page->execute( $sub );
+
+ if ( $out->getRedirect() !== '' ) {
+ $out->output();
+ $text = ob_get_contents();
+ } elseif ( $out->isDisabled() ) {
+ $text = ob_get_contents();
+ } else {
+ $text = $out->getHTML();
+ }
+
+ ob_end_clean();
+
+ $code = $response->getStatusCode();
+
+ if ( $code > 0 ) {
+ $response->header( "Status: " . $code . ' ' . \HttpStatus::getMessage( $code ) );
+ }
+
+ $this->text = $text;
+ $this->response = $response;
+ }
+
+ /**
+ * @return string
+ */
+ protected function getText() {
+ return $this->text;
+ }
+
+ /**
+ * @return FauxResponse
+ */
+ protected function getResponse() {
+ return $this->response;
+ }
+
+ /**
+ * @return RequestContext
+ */
+ private function makeRequestContext( WebRequest $request, $user, $title ) {
+
+ $context = new RequestContext();
+ $context->setRequest( $request );
+
+ $out = new OutputPage( $context );
+ $out->setTitle( $title );
+
+ $context->setOutput( $out );
+ $context->setLanguage( Language::factory( 'en' ) );
+
+ $user = $user === null ? new MockSuperUser() : $user;
+ $context->setUser( $user );
+
+ return $context;
+ }
+
+ /**
+ * Deprecated: Use of SpecialPage::getTitle was deprecated in MediaWiki 1.23
+ *
+ * @return Title
+ */
+ private function getTitle( SpecialPage $page ) {
+ return method_exists( $page, 'getPageTitle') ? $page->getPageTitle() : $page->getTitle();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestConfig.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestConfig.php
new file mode 100644
index 00000000..79394591
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestConfig.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ApplicationFactory;
+
+/**
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TestConfig {
+
+ /**
+ * @var Settings
+ */
+ private $settings;
+
+ /**
+ * @var array
+ */
+ private $configurations = [];
+
+ /**
+ * @var array
+ */
+ private $newKeys = [];
+
+ /**
+ * @since 3.0
+ */
+ public function __construct() {
+ $this->settings = ApplicationFactory::getInstance()->getSettings();
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param array $configurations
+ */
+ public function set( array $configurations = [] ) {
+
+ foreach ( $configurations as $key => $value ) {
+
+ if ( array_key_exists( $key, $GLOBALS ) ) {
+ $this->configurations[$key] = $GLOBALS[$key];
+ } else {
+ $this->newKeys[] = $key;
+ }
+
+ $GLOBALS[$key] = $value;
+ $this->settings->set( $key, $value );
+ }
+ }
+
+ /**
+ * @since 3.0
+ */
+ public function reset() {
+
+ foreach ( $this->configurations as $key => $value ) {
+ $GLOBALS[$key] = $value;
+ $this->settings->set( $key, $value );
+ }
+
+ foreach ( $this->newKeys as $key ) {
+ unset( $GLOBALS[$key] );
+ $this->settings->delete( $key );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestEnvironment.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestEnvironment.php
new file mode 100644
index 00000000..9e938212
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/TestEnvironment.php
@@ -0,0 +1,248 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\DeferredCallableUpdate;
+use SMW\Localizer;
+use SMW\Tests\Utils\Mock\ConfigurableStub;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class TestEnvironment {
+
+ /**
+ * @var ApplicationFactory
+ */
+ private $applicationFactory;
+
+ /**
+ * @var DataValueFactory
+ */
+ private $dataValueFactory;
+
+ /**
+ * @var TestConfig
+ */
+ private $testConfig;
+
+ /**
+ * @since 2.4
+ *
+ * @param array $configuration
+ */
+ public function __construct( array $configuration = [] ) {
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->testConfig = new TestConfig();
+
+ $this->withConfiguration( $configuration );
+ }
+
+ /**
+ * @since 2.4
+ */
+ public static function executePendingDeferredUpdates() {
+ DeferredCallableUpdate::releasePendingUpdates();
+ \DeferredUpdates::doUpdates();
+ }
+
+ /**
+ * @since 2.4
+ */
+ public static function clearPendingDeferredUpdates() {
+ DeferredCallableUpdate::releasePendingUpdates();
+ \DeferredUpdates::clearPendingUpdates();
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param string $key
+ * @param mixed $value
+ *
+ * @return self
+ */
+ public function addConfiguration( $key, $value ) {
+ return $this->withConfiguration( [ $key => $value ] );
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param array $configuration
+ *
+ * @return self
+ */
+ public function withConfiguration( array $configuration = [] ) {
+ $this->testConfig->set( $configuration );
+ return $this;
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param string $name
+ */
+ public function resetMediaWikiService( $name ) {
+
+ // MW 1.27+ (yet 1.27.0.rc has no access to "resetServiceForTesting")
+ if ( !class_exists( '\MediaWiki\MediaWikiServices' ) || !method_exists( \MediaWiki\MediaWikiServices::getInstance(), 'resetServiceForTesting' ) ) {
+ return null;
+ }
+
+ try {
+ \MediaWiki\MediaWikiServices::getInstance()->resetServiceForTesting( $name );
+ } catch( \Exception $e ) {
+ // Do nothing just avoid a
+ // MediaWiki\Services\NoSuchServiceException: No such service ...
+ }
+
+ if ( $name === 'MainWANObjectCache' ) {
+ \MediaWiki\MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
+ }
+
+ return $this;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $name
+ * @param callable $service
+ */
+ public function redefineMediaWikiService( $name, callable $service ) {
+
+ if ( !class_exists( '\MediaWiki\MediaWikiServices' ) ) {
+ return null;
+ }
+
+ $this->resetMediaWikiService( $name );
+
+ try {
+ \MediaWiki\MediaWikiServices::getInstance()->redefineService( $name, $service );
+ } catch( \Exception $e ) {
+ // Do nothing just avoid a
+ // MediaWiki\Services\NoSuchServiceException: No such service ...
+ }
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param string|array $poolCache
+ *
+ * @return self
+ */
+ public function resetPoolCacheById( $poolCache ) {
+
+ if ( is_array( $poolCache ) ) {
+ foreach ( $poolCache as $pc ) {
+ $this->resetPoolCacheById( $pc );
+ }
+ }
+
+ $this->applicationFactory->getInMemoryPoolCache()->resetPoolCacheById( $poolCache );
+
+ return $this;
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @param string $id
+ * @param mixed $object
+ *
+ * @return self
+ */
+ public function registerObject( $id, $object ) {
+ $this->applicationFactory->registerObject( $id, $object );
+ return $this;
+ }
+
+ /**
+ * @since 2.4
+ */
+ public function tearDown() {
+ $this->testConfig->reset();
+ $this->applicationFactory->clear();
+ $this->dataValueFactory->clear();
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param callable $callback
+ *
+ * @return string
+ */
+ public function outputFromCallbackExec( callable $callback ) {
+ ob_start();
+ call_user_func( $callback );
+ $output = ob_get_contents();
+ ob_end_clean();
+ return $output;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $pages
+ */
+ public function flushPages( $pages ) {
+ self::getUtilityFactory()->newPageDeleter()->doDeletePoolOfPages( $pages );
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @return UtilityFactory
+ */
+ public static function getUtilityFactory() {
+ return UtilityFactory::getInstance();
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @return ValidatorFactory
+ */
+ public static function newValidatorFactory() {
+ return UtilityFactory::getInstance()->newValidatorFactory();
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @return SpyLogger
+ */
+ public static function newSpyLogger() {
+ return self::getUtilityFactory()->newSpyLogger();
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param integer $index
+ * @param string $url
+ *
+ * @return string
+ */
+ public function replaceNamespaceWithLocalizedText( $index, $text ) {
+
+ $namespace = Localizer::getInstance()->getNamespaceTextById( $index );
+
+ return str_replace(
+ Localizer::getInstance()->getCanonicalNamespaceTextById( $index ) . ':',
+ $namespace . ':',
+ $text
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ApplicationFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ApplicationFactoryTest.php
new file mode 100644
index 00000000..7f24d50a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ApplicationFactoryTest.php
@@ -0,0 +1,328 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ApplicationFactory;
+
+/**
+ * @covers \SMW\ApplicationFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ApplicationFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\ApplicationFactory',
+ ApplicationFactory::getInstance()
+ );
+ }
+
+ public function testCanConstructSerializerFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\SerializerFactory',
+ $this->applicationFactory->newSerializerFactory()
+ );
+ }
+
+ public function testCanConstructJobFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\JobFactory',
+ $this->applicationFactory->newJobFactory()
+ );
+ }
+
+ public function testCanConstructParserFunctionFactory() {
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctionFactory',
+ $this->applicationFactory->newParserFunctionFactory( $parser )
+ );
+ }
+
+ public function testCanConstructQuerySourceFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\Query\QuerySourceFactory',
+ $this->applicationFactory->getQuerySourceFactory()
+ );
+ }
+
+ public function testGetStore() {
+
+ $this->assertInstanceOf(
+ '\SMW\Store',
+ $this->applicationFactory->getStore()
+ );
+ }
+
+ public function testGetSettings() {
+
+ $this->assertInstanceOf(
+ '\SMW\Settings',
+ $this->applicationFactory->getSettings()
+ );
+ }
+
+ public function testGetConnectionManager() {
+
+ $this->assertInstanceOf(
+ '\SMW\Connection\ConnectionManager',
+ $this->applicationFactory->getConnectionManager()
+ );
+ }
+
+ public function testCanConstructTitleFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\TitleFactory',
+ $this->applicationFactory->newTitleFactory()
+ );
+ }
+
+ public function testCanConstructPageCreator() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\PageCreator',
+ $this->applicationFactory->newPageCreator()
+ );
+ }
+
+ public function testCanConstructPageUpdater() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\PageUpdater',
+ $this->applicationFactory->newPageUpdater()
+ );
+ }
+
+ public function testCanConstructInTextAnnotationParser() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Parser\InTextAnnotationParser',
+ $this->applicationFactory->newInTextAnnotationParser( $parserData )
+ );
+ }
+
+ public function testCanConstructContentParser() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ContentParser',
+ $this->applicationFactory->newContentParser( $title )
+ );
+ }
+
+ public function testCanConstructMwCollaboratorFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MwCollaboratorFactory',
+ $this->applicationFactory->newMwCollaboratorFactory()
+ );
+ }
+
+ public function testCanConstructNamespaceExaminer() {
+
+ $this->assertInstanceOf(
+ '\SMW\NamespaceExaminer',
+ $this->applicationFactory->getNamespaceExaminer()
+ );
+ }
+
+ public function testCanConstructDataUpdater() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\DataUpdater',
+ $this->applicationFactory->newDataUpdater( $semanticData )
+ );
+ }
+
+ public function testCanConstructDataItemFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataItemFactory',
+ $this->applicationFactory->getDataItemFactory()
+ );
+ }
+
+ public function testCanConstructMaintenanceFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\MaintenanceFactory',
+ $this->applicationFactory->newMaintenanceFactory()
+ );
+ }
+
+ public function testCanConstructCacheFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\CacheFactory',
+ $this->applicationFactory->newCacheFactory()
+ );
+ }
+
+ public function testCanConstructIteratorFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\IteratorFactory',
+ $this->applicationFactory->getIteratorFactory()
+ );
+ }
+
+ public function testCanConstructDataValueFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValueFactory',
+ $this->applicationFactory->getDataValueFactory()
+ );
+ }
+
+ public function testCanConstructPropertySpecificationLookup() {
+
+ $this->assertInstanceOf(
+ '\SMW\PropertySpecificationLookup',
+ $this->applicationFactory->getPropertySpecificationLookup()
+ );
+ }
+
+ public function testCanConstructHierarchyLookup() {
+
+ $this->assertInstanceOf(
+ '\SMW\HierarchyLookup',
+ $this->applicationFactory->newHierarchyLookup()
+ );
+ }
+
+ public function testCanConstructCachedPropertyValuesPrefetcher() {
+
+ $this->assertInstanceOf(
+ '\SMW\CachedPropertyValuesPrefetcher',
+ $this->applicationFactory->getCachedPropertyValuesPrefetcher()
+ );
+ }
+
+ public function testCanConstructQueryFactory() {
+
+ $this->assertInstanceOf(
+ '\SMW\QueryFactory',
+ $this->applicationFactory->getQueryFactory()
+ );
+ }
+
+ public function testCanConstructPropertyLabelFinder() {
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyLabelFinder',
+ $this->applicationFactory->getPropertyLabelFinder()
+ );
+ }
+
+ public function testCanConstructDeferredCallableUpdate() {
+
+ $callback = function() {
+ return null;
+ };
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Deferred\CallableUpdate',
+ $this->applicationFactory->newDeferredCallableUpdate( $callback )
+ );
+ }
+
+ public function testCanConstructDeferredTransactionalCallableUpdate() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Deferred\TransactionalCallableUpdate',
+ $this->applicationFactory->newDeferredTransactionalCallableUpdate( null )
+ );
+ }
+
+ public function testCanConstructMediaWikiLogger() {
+
+ $this->assertInstanceOf(
+ '\Psr\Log\LoggerInterface',
+ $this->applicationFactory->getMediaWikiLogger()
+ );
+ }
+
+ public function testCanConstructJobQueue() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\JobQueue',
+ $this->applicationFactory->getJobQueue()
+ );
+ }
+
+ /**
+ * @dataProvider callbackContainerProvider
+ */
+ public function testCanConstructFromCallbackContainer( $service, $arguments, $expected ) {
+
+ array_unshift( $arguments, $service );
+
+ $this->assertInstanceOf(
+ $expected,
+ call_user_func_array( [ $this->applicationFactory, 'create' ], $arguments )
+ );
+ }
+
+ public function callbackContainerProvider() {
+
+ $provider[] = [
+ 'CachedQueryResultPrefetcher',
+ [],
+ '\SMW\Query\Result\CachedQueryResultPrefetcher'
+ ];
+
+ $provider[] = [
+ 'FactboxFactory',
+ [],
+ 'SMW\Factbox\FactboxFactory'
+ ];
+
+ $provider[] = [
+ 'PropertyAnnotatorFactory',
+ [],
+ 'SMW\PropertyAnnotatorFactory'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CacheFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CacheFactoryTest.php
new file mode 100644
index 00000000..93021425
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CacheFactoryTest.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace SMW\Tests;
+
+use Onoi\Cache\Cache;
+use Onoi\Cache\NullCache;
+use SMW\CacheFactory;
+
+/**
+ * @covers \SMW\CacheFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class CacheFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\CacheFactory',
+ new CacheFactory( 'hash' )
+ );
+ }
+
+ public function testGetMainCacheType() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->assertEquals(
+ 'hash',
+ $instance->getMainCacheType()
+ );
+
+ $instance = new CacheFactory( CACHE_NONE );
+
+ $this->assertEquals(
+ CACHE_NONE,
+ $instance->getMainCacheType()
+ );
+ }
+
+ public function testGetCachePrefix() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getCachePrefix()
+ );
+ }
+
+ public function testGetPurgeCacheKey() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getPurgeCacheKey( $title )
+ );
+ }
+
+ public function testCanConstructCacheOptions() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $cacheOptions = $instance->newCacheOptions( [
+ 'useCache' => true,
+ 'ttl' => 0
+ ] );
+
+ $this->assertTrue(
+ $cacheOptions->useCache
+ );
+ }
+
+ public function testIncompleteCacheOptionsThrowsException() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ $cacheOptions = $instance->newCacheOptions( [
+ 'useCache' => true
+ ] );
+ }
+
+ public function testCanConstructFixedInMemoryCache() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->assertInstanceOf(
+ 'Onoi\Cache\Cache',
+ $instance->newFixedInMemoryCache()
+ );
+ }
+
+ public function testCanConstructNullCache() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->assertInstanceOf(
+ 'Onoi\Cache\Cache',
+ $instance->newNullCache()
+ );
+ }
+
+ public function testCanConstructMediaWikiCompositeCache() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->assertInstanceOf(
+ 'Onoi\Cache\Cache',
+ $instance->newMediaWikiCompositeCache( CACHE_NONE )
+ );
+
+ $this->assertInstanceOf(
+ 'Onoi\Cache\Cache',
+ $instance->newMediaWikiCompositeCache( $instance->getMainCacheType() )
+ );
+ }
+
+ public function testCanConstructMediaWikiCache() {
+
+ $instance = new CacheFactory();
+
+ $this->assertInstanceOf(
+ Cache::class,
+ $instance->newMediaWikiCache( 'hash' )
+ );
+ }
+
+ public function testCanConstructCacheByType() {
+
+ $instance = new CacheFactory();
+
+ $this->assertInstanceOf(
+ NullCache::class,
+ $instance->newCacheByType( CACHE_NONE )
+ );
+
+ $this->assertInstanceOf(
+ Cache::class,
+ $instance->newCacheByType( 'hash' )
+ );
+ }
+
+ public function testCanConstructBlobStore() {
+
+ $instance = new CacheFactory( 'hash' );
+
+ $this->assertInstanceOf(
+ 'Onoi\BlobStore\BlobStore',
+ $instance->newBlobStore( 'foo', CACHE_NONE )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CachedPropertyValuesPrefetcherTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CachedPropertyValuesPrefetcherTest.php
new file mode 100644
index 00000000..f4e3d50d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CachedPropertyValuesPrefetcherTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\CachedPropertyValuesPrefetcher;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+
+/**
+ * @covers \SMW\CachedPropertyValuesPrefetcher
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class CachedPropertyValuesPrefetcherTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $blobStore;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->blobStore = $this->getMockBuilder( '\Onoi\BlobStore\BlobStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\CachedPropertyValuesPrefetcher',
+ new CachedPropertyValuesPrefetcher( $this->store, $this->blobStore )
+ );
+ }
+
+ public function testGetPropertyValues() {
+
+ $instance = new CachedPropertyValuesPrefetcher(
+ $this->store,
+ $this->blobStore
+ );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getPropertyValues( DIWikiPage::newFromText( 'Foo' ), new DIProperty( 'Bar' ) )
+ );
+ }
+
+ public function testQueryPropertyValuesFor() {
+
+ $expected = [
+ DIWikiPage::newFromText( 'Foo' )
+ ];
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( $expected ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new CachedPropertyValuesPrefetcher(
+ $this->store,
+ $this->blobStore
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->queryPropertyValuesFor( $query )
+ );
+ }
+
+ public function testGetPropertyValuesFromCache() {
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->atLeastOnce() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'Bar:123' ) )
+ ->will( $this->returnValue( 1001 ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $instance = new CachedPropertyValuesPrefetcher(
+ $this->store,
+ $this->blobStore
+ );
+
+ $this->assertEquals(
+ 1001,
+ $instance->getPropertyValues( DIWikiPage::newFromText( 'Foo#123' ), new DIProperty( 'Bar' ) )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ChangePropListenerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ChangePropListenerTest.php
new file mode 100644
index 00000000..f05ef0bf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ChangePropListenerTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ChangePropListener;
+use SMW\DIProperty;
+
+/**
+ * @covers \SMW\ChangePropListener
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangePropListenerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ChangePropListener::class,
+ new ChangePropListener()
+ );
+ }
+
+ public function testRegisterListenerAndCall() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->once() )
+ ->method( 'getSMWPropertyID' )
+ ->with( $this->equalTo( new DIProperty( __METHOD__ ) ) )
+ ->will( $this->returnValue( 42 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'execute' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'execute' )
+ ->with( $this->equalTo( [ 'Bar' ] ) );
+
+ $instance = new ChangePropListener();
+ $instance->clearListeners();
+
+ $instance->addListenerCallback( __METHOD__, function( $record ) use( $test ) {
+ $test->execute( $record );
+ } );
+
+ $instance->loadListeners( $store );
+
+ $instance->record( 42, [ 'Bar' ] );
+
+ $instance->callListeners();
+ TestEnvironment::executePendingDeferredUpdates();
+
+ $instance->clearListeners();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CompatibilityModeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CompatibilityModeTest.php
new file mode 100644
index 00000000..6ba5090e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/CompatibilityModeTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\CompatibilityMode;
+
+/**
+ * @covers \SMW\CompatibilityMode
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class CompatibilityModeTest extends \PHPUnit_Framework_TestCase {
+
+ public function testExtensionNotEnabled() {
+
+ $this->assertInternalType(
+ 'boolean',
+ CompatibilityMode::extensionNotEnabled()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/CallbackConnectionProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/CallbackConnectionProviderTest.php
new file mode 100644
index 00000000..11284691
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/CallbackConnectionProviderTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace SMW\Tests\Connection;
+
+use SMW\Connection\CallbackConnectionProvider;
+
+/**
+ * @covers \SMW\Connection\CallbackConnectionProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CallbackConnectionProviderTest extends \PHPUnit_Framework_TestCase {
+
+ private $conection;
+
+ public function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $callback = function() {};
+
+ $this->assertInstanceOf(
+ CallbackConnectionProvider::class,
+ new CallbackConnectionProvider( $callback )
+ );
+ }
+
+ public function getConnection() {
+ return $this->connection;
+ }
+
+ public function testGetConnectionFormCallback() {
+
+ $callback = function() {
+ return $this->connection;
+ };
+
+ $instance = new CallbackConnectionProvider(
+ $callback
+ );
+
+ $this->assertEquals(
+ $this->connection,
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetConnectionFormStaticCallback() {
+
+ $instance = new CallbackConnectionProvider(
+ [ $this, 'getConnection' ]
+ );
+
+ $this->assertEquals(
+ $this->connection,
+ $instance->getConnection()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionManagerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionManagerTest.php
new file mode 100644
index 00000000..353032d7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionManagerTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace SMW\Tests\Connection;
+
+use SMW\Connection\ConnectionManager;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Connection\ConnectionManager
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ConnectionManagerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConnectionManager::class,
+ new ConnectionManager()
+ );
+ }
+
+ public function testDefaultRegisteredConnectionProvided() {
+
+ $instance = new ConnectionManager();
+ $instance->releaseConnections();
+
+ $connection = $instance->getConnection( 'mw.db' );
+
+ $this->assertSame(
+ $connection,
+ $instance->getConnection( 'mw.db' )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Database',
+ $connection
+ );
+
+ $instance->releaseConnections();
+
+ $this->assertNotSame(
+ $connection,
+ $instance->getConnection( 'mw.db' )
+ );
+ }
+
+ public function testUnregisteredConnectionTypeThrowsException() {
+
+ $instance = new ConnectionManager();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getConnection( 'mw.master' );
+ }
+
+ public function testRegisterConnectionProvider() {
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->once() )
+ ->method( 'getConnection' );
+
+ $instance = new ConnectionManager();
+ $instance->registerConnectionProvider( 'foo', $connectionProvider );
+
+ $instance->getConnection( 'FOO' );
+ }
+
+ public function testRegisterCallbackConnection() {
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->once() )
+ ->method( 'getConnection' );
+
+ $callback = function() use( $connectionProvider ) {
+ return $connectionProvider->getConnection();
+ };
+
+ $instance = new ConnectionManager();
+ $instance->registerCallbackConnection( 'foo', $callback );
+
+ $instance->getConnection( 'FOO' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionProviderRefTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionProviderRefTest.php
new file mode 100644
index 00000000..87690be9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Connection/ConnectionProviderRefTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\Connection;
+
+use SMW\Connection\ConnectionProviderRef;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Connection\ConnectionProviderRef
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ConnectionProviderRefTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConnectionProviderRef::class,
+ new ConnectionProviderRef( [] )
+ );
+ }
+
+ public function testGetAndReleaseConnection() {
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ $connectionProvider->expects( $this->once() )
+ ->method( 'releaseConnection' );
+
+ $instance = new ConnectionProviderRef(
+ [
+ 'Foo' => $connectionProvider
+ ]
+ );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->getConnection( 'Foo' )
+ );
+
+ $instance->releaseConnection();
+ }
+
+ public function testNoMatchableConnectionProviderThrowsException() {
+
+ $instance = new ConnectionProviderRef(
+ [
+ 'Foo' => 'Bar'
+ ]
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getConnection( 'Foo' );
+ }
+
+ public function testNoMatchableKeyThrowsException() {
+
+ $instance = new ConnectionProviderRef( [] );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getConnection( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataItemFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataItemFactoryTest.php
new file mode 100644
index 00000000..ad5e6db4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataItemFactoryTest.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataItemFactory;
+use SMWDITime as DITime;
+use SMWDIUri as DIUri;
+
+/**
+ * @covers \SMW\DataItemFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DataItemFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataItemFactory',
+ new DataItemFactory()
+ );
+ }
+
+ public function testCanConstructDIError() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $instance->newDIError( 'Foo' )
+ );
+ }
+
+ public function testCanConstructDIProperty() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\DIProperty',
+ $instance->newDIProperty( 'Foo bar' )
+ );
+ }
+
+ public function testCanConstructDIWikiPage() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $instance->newDIWikiPage( 'Foo' )
+ );
+ }
+
+ public function testCanConstructDIWikiPageFromTitle() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $instance->newDIWikiPage( $title )
+ );
+ }
+
+ public function testCanConstructDIContainer() {
+
+ $containerSemanticData = $this->getMockBuilder( '\SMWContainerSemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $instance->newDIContainer( $containerSemanticData )
+ );
+ }
+
+ public function testCanConstructContainerSemanticData() {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\DataModel\ContainerSemanticData',
+ $instance->newContainerSemanticData( $subject )
+ );
+ }
+
+ public function testCanConstructDINumber() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMWDINumber',
+ $instance->newDINumber( 42 )
+ );
+ }
+
+ public function testCanConstructDIBlob() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMWDIBlob',
+ $instance->newDIBlob( 'Foo' )
+ );
+ }
+
+ public function testCanConstructDIBoolean() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMWDIBoolean',
+ $instance->newDIBoolean( true )
+ );
+ }
+
+ public function testCanConstructDIConcept() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\DIConcept',
+ $instance->newDIConcept( 'Foo' )
+ );
+ }
+
+ public function testCanConstructDIUri() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ DIUri::class,
+ $instance->newDIUri( 'http', 'example.org' )
+ );
+ }
+
+ public function testCanConstructDITime() {
+
+ $instance = new DataItemFactory();
+
+ $this->assertInstanceOf(
+ DITime::class,
+ $instance->newDITime( 1, '1900' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/ContainerSemanticDataTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/ContainerSemanticDataTest.php
new file mode 100644
index 00000000..63389173
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/ContainerSemanticDataTest.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace SMW\Tests\DataModel;
+
+use SMW\DataItemFactory;
+use SMW\DataModel\ContainerSemanticData;
+use SMW\SemanticData;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataModel\ContainerSemanticData
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ContainerSemanticDataTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ContainerSemanticData::class,
+ new ContainerSemanticData( $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN ) )
+ );
+ }
+
+ public function testMakeAnonymousContainer() {
+
+ $instance = ContainerSemanticData::makeAnonymousContainer();
+ $instance->skipAnonymousCheck();
+
+ $this->assertInstanceOf(
+ ContainerSemanticData::class,
+ $instance
+ );
+
+ $this->assertTrue(
+ $instance->hasAnonymousSubject()
+ );
+ }
+
+ public function testGetSubjectOnAnonymousContainerWithoutSkipThrowsException() {
+
+ $instance = ContainerSemanticData::makeAnonymousContainer();
+
+ $this->setExpectedException( '\SMW\Exception\DataItemException' );
+ $instance->getSubject();
+ }
+
+ public function testCopyDataFrom() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN );
+
+ $semanticData = new SemanticData(
+ $subject
+ );
+
+ $instance = ContainerSemanticData::makeAnonymousContainer( true, true );
+
+ $this->assertNotEquals(
+ $subject,
+ $instance->getSubject()
+ );
+
+ $instance->copyDataFrom( $semanticData );
+
+ $this->assertEquals(
+ $subject,
+ $instance->getSubject()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/SubSemanticDataTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/SubSemanticDataTest.php
new file mode 100644
index 00000000..28b0cedf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataModel/SubSemanticDataTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace SMW\Tests\DataModel;
+
+use SMW\DataItemFactory;
+use SMW\DataModel\ContainerSemanticData;
+use SMW\DataModel\SubSemanticData;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataModel\SubSemanticData
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SubSemanticDataTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SubSemanticData::class,
+ new SubSemanticData( $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN ) )
+ );
+ }
+
+ public function testAddSubSemanticData() {
+
+ $instance = new SubSemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN )
+ );
+
+ $this->assertEmpty(
+ $instance->getSubSemanticData()
+ );
+
+ $containerSemanticData = new ContainerSemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN, '', 'Foo' )
+ );
+
+ $instance->addSubSemanticData(
+ $containerSemanticData
+ );
+
+ $this->assertNotEmpty(
+ $instance->getSubSemanticData()
+ );
+ }
+
+ public function testAddSubSemanticDataWithMismatchedSubjectThrowsException() {
+
+ $instance = new SubSemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN )
+ );
+
+ $this->setExpectedException( '\SMW\Exception\SubSemanticDataException');
+
+ $instance->addSubSemanticData(
+ ContainerSemanticData::makeAnonymousContainer( true, true )
+ );
+ }
+
+ public function testRemoveSubSemanticData() {
+
+ $instance = new SubSemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN )
+ );
+
+ $containerSemanticData = new ContainerSemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN, '', 'Foo' )
+ );
+
+ $instance->addSubSemanticData(
+ $containerSemanticData
+ );
+
+ $this->assertTrue(
+ $instance->hasSubSemanticData( 'Foo' )
+ );
+
+ $instance->removeSubSemanticData(
+ $containerSemanticData
+ );
+
+ $this->assertFalse(
+ $instance->hasSubSemanticData( 'Foo' )
+ );
+ }
+
+ public function testRemoveProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new SubSemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN )
+ );
+
+ $containerSemanticData = new ContainerSemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_MAIN, '', 'Foo' )
+ );
+
+ $containerSemanticData->addPropertyObjectValue(
+ $property,
+ $this->dataItemFactory->newDIBlob( 'Bar' )
+ );
+
+ $instance->addSubSemanticData(
+ $containerSemanticData
+ );
+
+ $subSemanticData = $instance->findSubSemanticData( 'Foo' );
+
+ $this->assertTrue(
+ $subSemanticData->hasProperty( $property )
+ );
+
+ $instance->removeProperty(
+ $property
+ );
+
+ $this->assertFalse(
+ $subSemanticData->hasProperty( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataTypeRegistryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataTypeRegistryTest.php
new file mode 100644
index 00000000..b4477bc4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataTypeRegistryTest.php
@@ -0,0 +1,454 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataTypeRegistry;
+use SMWDataItem as DataItem;
+
+/**
+ * @covers \SMW\DataTypeRegistry
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DataTypeRegistryTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataTypeRegistry;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataTypeRegistry = DataTypeRegistry::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->dataTypeRegistry->clear();
+
+ parent::tearDown();
+ }
+
+ public function testGetInstance() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataTypeRegistry',
+ $this->dataTypeRegistry
+ );
+
+ $this->assertSame(
+ $this->dataTypeRegistry,
+ DataTypeRegistry::getInstance()
+ );
+
+ DataTypeRegistry::clear();
+
+ $this->assertNotSame(
+ $this->dataTypeRegistry,
+ DataTypeRegistry::getInstance()
+ );
+ }
+
+ public function testIsEqualItemType() {
+
+ $this->assertTrue(
+ $this->dataTypeRegistry->isEqualByType( '_wpg', '__sob' )
+ );
+
+ $this->assertFalse(
+ $this->dataTypeRegistry->isEqualByType( '_wpg', '_txt' )
+ );
+ }
+
+ public function testRegisterDatatype() {
+
+ $this->assertNull(
+ $this->dataTypeRegistry->getDataTypeClassById( '_foo' ),
+ 'Asserts that prior registration getDataTypeClassById() returns null'
+ );
+
+ $this->dataTypeRegistry
+ ->registerDataType( '_foo', '\SMW\Tests\FooValue', DataItem::TYPE_NOTYPE, 'FooValue' );
+
+ $this->assertEquals(
+ '\SMW\Tests\FooValue',
+ $this->dataTypeRegistry->getDataTypeClassById( '_foo' ),
+ 'Asserts that getDataTypeClassById() returns the registered class'
+ );
+
+ $this->assertEquals(
+ DataItem::TYPE_NOTYPE,
+ $this->dataTypeRegistry->getDataItemId( '_foo' )
+ );
+
+ $this->assertEquals(
+ 'FooValue',
+ $this->dataTypeRegistry->findTypeLabel( '_foo' )
+ );
+
+ $this->assertEmpty(
+ $this->dataTypeRegistry->findTypeLabel( 'FooNoLabel' )
+ );
+
+ $this->assertEquals(
+ DataItem::TYPE_NOTYPE,
+ $this->dataTypeRegistry->getDataItemId( 'FooBar' )
+ );
+ }
+
+ public function testRegisterDatatypeIdAndAlias() {
+
+ $this->dataTypeRegistry
+ ->registerDataType( '_foo', '\SMW\Tests\FooValue', DataItem::TYPE_NOTYPE, 'FooValue' );
+
+ $this->assertEmpty(
+ $this->dataTypeRegistry->findTypeByLabel( 'FooBar' )
+ );
+
+ $this->dataTypeRegistry->registerDataTypeAlias( '_foo', 'FooBar' );
+
+ $this->assertTrue(
+ $this->dataTypeRegistry->isRegistered( '_foo' )
+ );
+
+ $this->assertEquals(
+ '_foo',
+ $this->dataTypeRegistry->findTypeByLabel( 'FooBar' ),
+ 'Asserts that findTypeByLabel returns the registered alias label'
+ );
+ }
+
+ public function testGetDefaultDataItemTypeIdForValidDataItemType() {
+ $this->assertInternalType(
+ 'string',
+ $this->dataTypeRegistry->getDefaultDataItemByType( 1 )
+ );
+ }
+
+ public function testGetDefaultDataItemTypeIdForInvalidDataItemType() {
+ $this->assertNull(
+ $this->dataTypeRegistry->getDefaultDataItemByType( 9999 )
+ );
+ }
+
+ public function testFindCanonicalLabelById() {
+ $this->assertSame(
+ 'Text',
+ $this->dataTypeRegistry->findCanonicalLabelById( '_txt' )
+ );
+ }
+
+ public function testTypeIdAndLabelAsLanguageIndependantInvocation() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [ '_wpg' => 'Page' ] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [ 'URI' => '_uri' ] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ $this->assertEquals(
+ '_wpg',
+ $instance->findTypeByLabel( 'Page' ),
+ 'Asserts that findTypeByLabel returns empty label'
+ );
+
+ $this->assertEquals(
+ [ '_wpg' => 'Page' ],
+ $instance->getKnownTypeLabels(),
+ 'Asserts that getKnownTypeLabels returns an array'
+ );
+ }
+
+ public function testKnownAliasAsLanguageIndependantInvocation() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [ 'URI' => '_uri' ] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ $this->assertEquals(
+ [ 'URI' => '_uri' ],
+ $instance->getKnownTypeAliases(),
+ 'Asserts that getKnownTypeAliases returns an array'
+ );
+ }
+
+ public function testExtraneousCallbackFunction() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry( $lang );
+ $arg = 'foo';
+
+ $instance->registerExtraneousFunction(
+ 'foo',
+ function ( $arg ) {
+ return 'bar' . $arg;
+ }
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getExtraneousFunctions()
+ );
+ }
+
+ public function testLookupByLabelIsCaseInsensitive() {
+ $caseVariants = [
+ 'page',
+ 'Page',
+ 'PAGE',
+ 'pAgE',
+ ];
+
+ foreach ( $caseVariants as $caseVariant ) {
+ $this->assertRegistryFindsIdForLabels( $caseVariant, $caseVariants );
+ $this->assertRegistryFindsIdForAliases( $caseVariant, $caseVariants );
+ }
+ }
+
+ public function testFindTypeByLabelAndLanguage() {
+
+ $this->assertSame(
+ '_num',
+ $this->dataTypeRegistry->findTypeByLabelAndLanguage( 'Número', 'es' )
+ );
+
+ $this->assertSame(
+ '_num',
+ $this->dataTypeRegistry->findTypeByLabelAndLanguage( '数值型', 'zh-Hans' )
+ );
+ }
+
+ public function testSubDataType() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ $instance->registerDataType( '_foo', 'FooValue', DataItem::TYPE_NOTYPE, false, true );
+
+ $this->assertTrue(
+ $instance->isSubDataType( '_foo' )
+ );
+ }
+
+ public function testBrowsableType() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ $instance->registerDataType( '_foo', 'FooValue', DataItem::TYPE_NOTYPE, false, true, true );
+ $instance->registerDataType( '_bar', 'BarValue', DataItem::TYPE_NOTYPE );
+
+ $this->assertTrue(
+ $instance->isBrowsableType( '_foo' )
+ );
+
+ $this->assertFalse(
+ $instance->isBrowsableType( '_bar' )
+ );
+ }
+
+ public function testGetFieldType() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ $instance->registerDataType( '_foo', 'FooValue', DataItem::TYPE_BLOB, false, true );
+
+ $this->assertEquals(
+ '_txt',
+ $instance->getFieldType( '_foo' )
+ );
+ }
+
+ protected function assertRegistryFindsIdForLabels( $inputLabel, array $equivalentLabels ) {
+
+ $id = '_wpg';
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [ $inputLabel => $id ] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ foreach ( $equivalentLabels as $caseVariant ) {
+ $this->assertEquals( $id, $instance->findTypeByLabel( $caseVariant ) );
+ }
+ }
+
+ protected function assertRegistryFindsIdForAliases( $inputLabel, array $equivalentLabels ) {
+ $id = '_wpg';
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [ $id => $inputLabel ] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ foreach ( $equivalentLabels as $caseVariant ) {
+ $this->assertEquals( $id, $instance->findTypeByLabel( $caseVariant ) );
+ }
+ }
+
+ public function testExtensionData() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getDatatypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getCanonicalDatatypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DataTypeRegistry(
+ $lang
+ );
+
+ $instance->registerDataType(
+ '__foo', '\SMW\Tests\FooValue', DataItem::TYPE_NOTYPE, 'FooValue'
+ );
+
+ $instance->setExtensionData( '__foo', [ 'ext.test' => 'test' ] );
+
+ $this->assertEquals(
+ [ 'ext.test' => 'test' ],
+ $instance->getExtensionData( '__foo' )
+ );
+ }
+
+}
+
+class FooValue {
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataUpdaterTest.php
new file mode 100644
index 00000000..5ee34e2d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataUpdaterTest.php
@@ -0,0 +1,352 @@
+<?php
+
+namespace SMW\Tests\Updater;
+
+use SMW\DataUpdater;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DataUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $transactionalCallableUpdate;
+ private $semanticDataFactory;
+ private $spyLogger;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment( [
+ 'smwgPageSpecialProperties' => [],
+ 'smwgEnableUpdateJobs' => false,
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ]
+ ] );
+
+ $this->spyLogger = $this->testEnvironment->newSpyLogger();
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->store->setLogger( $this->spyLogger );
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+
+ $this->transactionalCallableUpdate = $this->getMockBuilder( '\SMW\MediaWiki\Deferred\TransactionalCallableUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'DeferredTransactionalCallableUpdate', $this->transactionalCallableUpdate );
+
+ $this->semanticDataFactory = $this->testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ DataUpdater::class,
+ new DataUpdater( $this->store, $semanticData )
+ );
+ }
+
+ public function testDoUpdateForDefaultSettings() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $instance = new DataUpdater(
+ $this->store,
+ $semanticData
+ );
+
+ $this->assertTrue(
+ $instance->doUpdate()
+ );
+ }
+
+ public function testDeferredUpdate() {
+
+ $this->transactionalCallableUpdate->expects( $this->once() )
+ ->method( 'pushUpdate' );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $instance = new DataUpdater(
+ $this->store,
+ $semanticData
+ );
+
+ $instance->isDeferrableUpdate( true );
+ $instance->doUpdate();
+ }
+
+ /**
+ * @dataProvider updateJobStatusProvider
+ */
+ public function testDoUpdateForValidRevision( $updateJobStatus ) {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'updateData' );
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content = $this->getMockBuilder( '\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( $content ) );
+
+ $wikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getRevision' )
+ ->will( $this->returnValue( $revision ) );
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $this->atLeastOnce() )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $wikiPage ) );
+
+ $this->testEnvironment->registerObject( 'PageCreator', $pageCreator );
+
+ $instance = new DataUpdater(
+ $store,
+ $semanticData
+ );
+
+ $instance->canCreateUpdateJob(
+ $updateJobStatus
+ );
+
+ $this->assertTrue(
+ $instance->doUpdate()
+ );
+ }
+
+ /**
+ * @dataProvider updateJobStatusProvider
+ */
+ public function testDoUpdateForNullRevision( $updateJobStatus ) {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $idTable->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'clearData', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->once() )
+ ->method( 'clearData' )
+ ->with( $this->equalTo( $semanticData->getSubject() ) );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $this->atLeastOnce() )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $wikiPage ) );
+
+ $this->testEnvironment->registerObject( 'PageCreator', $pageCreator );
+
+ $instance = new DataUpdater(
+ $store,
+ $semanticData
+ );
+
+ $instance->canCreateUpdateJob(
+ $updateJobStatus
+ );
+
+ $this->assertTrue(
+ $instance->doUpdate()
+ );
+ }
+
+ public function testDoUpdateForTitleInUnknownNs() {
+
+ $wikiPage = new DIWikiPage(
+ 'Foo',
+ -32768, // This namespace does not exist
+ ''
+ );
+
+ $semanticData = $this->semanticDataFactory->setSubject( $wikiPage )->newEmptySemanticData();
+
+ $instance = new DataUpdater(
+ $this->store,
+ $semanticData
+ );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->doUpdate()
+ );
+ }
+
+ public function testDoUpdateForSpecialPage() {
+
+ $wikiPage = new DIWikiPage(
+ 'Foo',
+ NS_SPECIAL,
+ ''
+ );
+
+ $semanticData = $this->semanticDataFactory->setSubject( $wikiPage )->newEmptySemanticData();
+
+ $instance = new DataUpdater(
+ $this->store,
+ $semanticData
+ );
+
+ $this->assertFalse(
+ $instance->doUpdate()
+ );
+ }
+
+ public function testForYetUnknownRedirectTarget() {
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content = $this->getMockBuilder( '\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( $content ) );
+
+ $wikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getRevision' )
+ ->will( $this->returnValue( $revision ) );
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $this->atLeastOnce() )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $wikiPage ) );
+
+ $this->testEnvironment->registerObject( 'PageCreator', $pageCreator );
+
+ $source = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject = new DIWikiPage(
+ 'Foo',
+ NS_MAIN
+ );
+
+ $target = new DIWikiPage(
+ 'Bar',
+ NS_MAIN
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'changeTitle' );
+
+ $store->setOption( 'smwgSemanticsEnabled', true );
+ $store->setOption( 'smwgAutoRefreshSubject', true );
+
+ $store->setLogger( $this->spyLogger );
+
+ $semanticData = new SemanticData( $subject );
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_REDI' ),
+ $target
+ );
+
+ $instance = new DataUpdater(
+ $store,
+ $semanticData
+ );
+
+ $instance->canCreateUpdateJob( true );
+ $instance->doUpdate();
+ }
+
+ public function updateJobStatusProvider() {
+
+ $provider = [
+ [ true ],
+ [ false ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValueFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValueFactoryTest.php
new file mode 100644
index 00000000..65c0dcb1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValueFactoryTest.php
@@ -0,0 +1,341 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMWDataItem;
+
+/**
+ * @covers \SMW\DataValueFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DataValueFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ protected function tearDown() {
+ DataValueFactory::getInstance()->clear();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider typeIdValueDataProvider
+ */
+ public function testNewTypeIdValue( $typeId, $value, $expectedValue, $expectedInstance ) {
+
+ $dataValue = DataValueFactory::getInstance()->newTypeIdValue( $typeId, $value );
+
+ $this->assertInstanceOf(
+ $expectedInstance,
+ $dataValue
+ );
+
+ if ( $dataValue->getErrors() === [] ){
+ return $this->assertEquals(
+ $expectedValue,
+ $dataValue->getWikiValue()
+ );
+ }
+
+ $this->assertInternalType(
+ 'array',
+ $dataValue->getErrors()
+ );
+ }
+
+ /**
+ * @dataProvider propertyObjectValueDataProvider
+ */
+ public function testNewPropertyObjectValue( $propertyName, $value, $expectedValue, $expectedInstance ) {
+
+ $propertyDV = DataValueFactory::getInstance()->newPropertyValueByLabel( $propertyName );
+ $propertyDI = $propertyDV->getDataItem();
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByProperty( $propertyDI, $value );
+
+ // Check the returned instance
+ $this->assertInstanceOf( $expectedInstance, $dataValue );
+
+ if ( $dataValue->getErrors() === [] ){
+ $this->assertInstanceOf( 'SMWDIProperty', $dataValue->getProperty() );
+ $this->assertContains( $propertyName, $dataValue->getProperty()->getLabel() );
+ if ( $dataValue->getDataItem()->getDIType() === SMWDataItem::TYPE_WIKIPAGE ){
+ $this->assertEquals( $expectedValue, $dataValue->getWikiValue() );
+ }
+ } else {
+ $this->assertInternalType( 'array', $dataValue->getErrors() );
+ }
+
+ // Check interface parameters
+ $dataValue = DataValueFactory::getInstance()->newDataValueByProperty(
+ $propertyDI,
+ $value,
+ 'FooCaption',
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $this->assertInstanceOf(
+ $expectedInstance,
+ $dataValue
+ );
+ }
+
+ /**
+ * @dataProvider propertyValueDataProvider
+ */
+ public function testAddPropertyValueByText( $propertyName, $value, $expectedValue, $expectedInstance ) {
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByText( $propertyName, $value );
+
+ // Check the returned instance
+ $this->assertInstanceOf( $expectedInstance, $dataValue );
+
+ if ( $dataValue->getErrors() === [] ){
+ $this->assertInstanceOf( 'SMWDIProperty', $dataValue->getProperty() );
+ $this->assertContains( $propertyName, $dataValue->getProperty()->getLabel() );
+ if ( $dataValue->getDataItem()->getDIType() === SMWDataItem::TYPE_WIKIPAGE ){
+ $this->assertEquals( $expectedValue, $dataValue->getWikiValue() );
+ }
+ } else {
+ $this->assertInternalType( 'array', $dataValue->getErrors() );
+ }
+
+ // Check interface parameters
+ $dataValue = DataValueFactory::getInstance()->newDataValueByText(
+ $propertyName,
+ $value,
+ 'FooCaption',
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $this->assertInstanceOf(
+ $expectedInstance,
+ $dataValue
+ );
+ }
+
+ public function testTryToCreateDataValueUsingRestrictedPropertyValue() {
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByText( 'Has subobject', 'Foo' );
+
+ $this->assertInstanceOf(
+ '\SMWErrorValue',
+ $dataValue
+ );
+
+ $this->assertNotEmpty(
+ $dataValue->getErrors()
+ );
+ }
+
+ public function testToCreateDataValueUsingLegacyNewPropertyValueMethod() {
+
+ $dataValue = DataValueFactory::getInstance()->newPropertyValue( 'Bar', 'Foo' );
+
+ $this->assertInstanceOf(
+ '\SMWDataValue',
+ $dataValue
+ );
+ }
+
+ /**
+ * Issue 673
+ */
+ public function testEnforceFirstUpperCaseForDisabledCapitalLinks() {
+
+ $wgCapitalLinks = $GLOBALS['wgCapitalLinks'];
+ $GLOBALS['wgCapitalLinks'] = false;
+
+ $instance = DataValueFactory::getInstance();
+
+ $dataValue = $instance->newDataValueByText(
+ 'has type',
+ 'number',
+ null,
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY )
+ );
+
+ $this->assertEquals(
+ '_TYPE',
+ $dataValue->getProperty()->getKey()
+ );
+
+ $GLOBALS['wgCapitalLinks'] = $wgCapitalLinks;
+ }
+
+ public function testNewPropertyValueByLabel() {
+
+ $dataValue = DataValueFactory::getInstance()->newPropertyValueByLabel(
+ 'Foo',
+ 'Bar',
+ new DIWikiPage( 'Foobar', SMW_NS_PROPERTY )
+ );
+
+ $this->assertInstanceOf(
+ '\SMWPropertyValue',
+ $dataValue
+ );
+
+ $this->assertSame(
+ 'Bar',
+ $dataValue->getCaption()
+ );
+ }
+
+ /**
+ * @dataProvider newDataValueByItemDataProvider
+ */
+ public function testNewDataItemValue( $setup ) {
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByItem(
+ $setup['dataItem'],
+ $setup['property'],
+ $setup['caption']
+ );
+
+ $this->assertInstanceOf(
+ 'SMWDataValue',
+ $dataValue
+ );
+ }
+
+ public function newDataValueByItemDataProvider() {
+
+ $provider = [];
+
+ $dataItem = new DIWikiPage( 'Foo', NS_MAIN );
+ $property = new DIProperty( 'Bar' );
+
+ // #0
+ $provider[] = [
+ [
+ 'dataItem' => $dataItem,
+ 'property' => null,
+ 'caption' => false
+ ]
+ ];
+
+ // #0
+ $provider[] = [
+ [
+ 'dataItem' => $dataItem,
+ 'property' => $property,
+ 'caption' => false
+ ]
+ ];
+
+ // #1
+ $provider[] = [
+ [
+ 'dataItem' => $dataItem,
+ 'property' => null,
+ 'caption' => 'Foo'
+ ]
+ ];
+
+ // #2
+ $provider[] = [
+ [
+ 'dataItem' => $dataItem,
+ 'property' => $property,
+ 'caption' => 'Bar'
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function findTypeIdDataProvider() {
+ return [
+ [ 'URL' , '_uri' ], // #0
+ [ 'Page' , '_wpg' ], // #1
+ [ 'String' , '_txt' ], // #2
+ [ 'Text' , '_txt' ], // #3
+ [ 'Number' , '_num' ], // #4
+ [ 'Quantity' , '_qty' ], // #5
+ [ 'Date' , '_dat' ], // #6
+ [ 'Email' , '_ema' ], // #7
+ [ '' , '' ], // #8
+ ];
+ }
+
+ public function dataItemIdDataProvider() {
+ return [
+ [ '_txt' , SMWDataItem::TYPE_BLOB ], // #0
+ [ '_wpg' , SMWDataItem::TYPE_WIKIPAGE ], // #1
+ [ '_num' , SMWDataItem::TYPE_NUMBER ], // #2
+ [ '_dat' , SMWDataItem::TYPE_TIME ], // #3
+ [ '_uri' , SMWDataItem::TYPE_URI ], // #4
+ [ '_foo' , SMWDataItem::TYPE_NOTYPE ], // #5
+ ];
+ }
+
+ public function typeIdValueDataProvider() {
+ return [
+ [ '_txt' , 'Bar' , 'Bar' , 'SMWStringValue' ], // #0
+ [ '_txt' , 'Bar[[ Foo ]]' , 'Bar[[ Foo ]]' , 'SMWStringValue' ], // #1
+ [ '_txt' , '9001' , '9001' , 'SMWStringValue' ], // #2
+ [ '_txt' , 1001 , '1001' , 'SMWStringValue' ], // #3
+ [ '_txt' , '-%&$*' , '-%&$*' , 'SMWStringValue' ], // #4
+ [ '_txt' , '_Bar' , '_Bar' , 'SMWStringValue' ], // #5
+ [ '_txt' , 'bar' , 'bar' , 'SMWStringValue' ], // #6
+ [ '-_txt' , 'Bar' , 'Bar' , 'SMWErrorValue' ], // #7
+
+ [ '_wpg' , 'Bar' , 'Bar' , 'SMWWikiPageValue' ], // #8
+ [ '_wpg' , 'Bar' , 'Bar' , 'SMWWikiPageValue' ], // #9
+ [ '_wpg' , 'Bar[[ Foo ]]' , 'Bar[[ Foo ]]' , 'SMWWikiPageValue' ], // #10
+ [ '_wpg' , '9001' , '9001' , 'SMWWikiPageValue' ], // #11
+ [ '_wpg' , 1001 , '1001' , 'SMWWikiPageValue' ], // #12
+ [ '_wpg' , '-%&$*' , '-%&$*' , 'SMWWikiPageValue' ], // #13
+ [ '_wpg' , '_Bar' , 'Bar' , 'SMWWikiPageValue' ], // #14
+ [ '_wpg' , 'bar' , 'Bar' , 'SMWWikiPageValue' ], // #15
+ [ '-_wpg' , 'Bar' , 'Bar' , 'SMWErrorValue' ], // #16
+
+ [ '_dat' , '1 Jan 1970' , '1 Jan 1970' , 'SMWTimeValue' ], // #0
+ [ '_uri' , 'Foo' , 'Foo' , 'SMWURIValue' ], // #0
+ [ '_num' , 9001 , '9001' , 'SMWNumberValue' ], // #0
+ [ '_num' , 9001.5 , '9001.5' , 'SMWNumberValue' ], // #0
+ ];
+ }
+
+ public function propertyValueDataProvider() {
+ return [
+ [ 'Foo' , 'Bar' , 'Bar' , 'SMWDataValue' ], // #0
+ [ 'Foo' , 'Bar[[ Foo ]]' , 'Bar[[ Foo ]]' , 'SMWDataValue' ], // #1
+ [ 'Foo' , '9001' , '9001' , 'SMWDataValue' ], // #2
+ [ 'Foo' , 1001 , '1001' , 'SMWDataValue' ], // #3
+ [ 'Foo' , '-%&$*' , '-%&$*' , 'SMWDataValue' ], // #4
+ [ 'Foo' , '_Bar' , 'Bar' , 'SMWDataValue' ], // #5
+ [ 'Foo' , 'bar' , 'Bar' , 'SMWDataValue' ], // #6
+ [ '-Foo' , 'Bar' , '' , 'SMWErrorValue' ], // #7
+ [ '_Foo' , 'Bar' , '' , 'SMWPropertyValue' ], // #8
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ public function propertyObjectValueDataProvider() {
+ return [
+ [ 'Foo' , 'Bar' , 'Bar' , 'SMWDataValue' ], // #0
+ [ 'Foo' , 'Bar[[ Foo ]]' , 'Bar[[ Foo ]]' , 'SMWDataValue' ], // #1
+ [ 'Foo' , '9001' , '9001' , 'SMWDataValue' ], // #2
+ [ 'Foo' , 1001 , '1001' , 'SMWDataValue' ], // #3
+ [ 'Foo' , '-%&$*' , '-%&$*' , 'SMWDataValue' ], // #4
+ [ 'Foo' , '_Bar' , 'Bar' , 'SMWDataValue' ], // #5
+ [ 'Foo' , 'bar' , 'Bar' , 'SMWDataValue' ], // #6
+ [ '-Foo' , 'Bar' , 'Bar' , 'SMWWikiPageValue' ], // #7
+
+ // Will fail with "must be an instance of SMWDIProperty, instance of SMWDIError give"
+ // as propertyDI isn't checked therefore addPropertyValue() should be
+ // used as it will return a proper object
+ // array( '_Foo' , 'Bar' , '' , 'SMWDIProperty' ), // #8
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsListValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsListValueTest.php
new file mode 100644
index 00000000..27529573
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsListValueTest.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\AllowsListValue;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\AllowsListValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class AllowsListValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $dataValueServiceFactory;
+ private $propertySpecificationLookup;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ AllowsListValue::class,
+ new AllowsListValue()
+ );
+ }
+
+ public function testGetShortWikiText() {
+
+ $instance = new AllowsListValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setDataItem(
+ $this->dataItemFactory->newDIBlob( 'Foo' )
+ );
+
+ $this->assertContains(
+ '[[MediaWiki:Smw_allows_list_Foo|Foo]]',
+ $instance->getShortWikiText()
+ );
+ }
+
+ public function testGetLongHtmlText() {
+
+ $instance = new AllowsListValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setDataItem(
+ $this->dataItemFactory->newDIBlob( 'Foo' )
+ );
+
+ $this->assertContains(
+ 'MediaWiki:Smw_allows_list_Foo',
+ $instance->getLongHtmlText()
+ );
+ }
+
+ public function testGetShortHtmlText() {
+
+ $instance = new AllowsListValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setDataItem(
+ $this->dataItemFactory->newDIBlob( 'Foo' )
+ );
+
+ $this->assertContains(
+ 'MediaWiki:Smw_allows_list_Foo',
+ $instance->getShortHtmlText()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsPatternValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsPatternValueTest.php
new file mode 100644
index 00000000..8fe21499
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/AllowsPatternValueTest.php
@@ -0,0 +1,220 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\AllowsPatternValue;
+use SMW\DataValues\ValueParsers\AllowsPatternValueParser;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\AllowsPatternValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class AllowsPatternValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $dataValueServiceFactory;
+ private $constraintValueValidator;
+
+ protected function setUp() {
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->mediaWikiNsContentReader = $this->getMockBuilder( '\SMW\MediaWiki\MediaWikiNsContentReader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'MediaWikiNsContentReader', $this->mediaWikiNsContentReader );
+
+ $propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $propertySpecificationLookup );
+
+ $this->constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( new AllowsPatternValueParser( $this->mediaWikiNsContentReader ) ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $this->constraintValueValidator ) );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\AllowsPatternValue',
+ new AllowsPatternValue()
+ );
+ }
+
+ public function testHasErrorForMissingValue() {
+
+ $instance = new AllowsPatternValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setOption( 'smwgDVFeatures', SMW_DV_PVAP );
+
+ $instance->setUserValue( '' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testHasErrorForNonMatchingContent() {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( " \nFoo|Bar\n" ) );
+
+ $instance = new AllowsPatternValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setOption( 'smwgDVFeatures', SMW_DV_PVAP );
+
+ $instance->setUserValue( 'NotMatchable' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testHasNoErrorOnMatchableContent() {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( " \nFoo|Bar\n" ) );
+
+ $instance = new AllowsPatternValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setOption( 'smwgDVFeatures', SMW_DV_PVAP );
+
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testErrorOnNotEnabledFeatureWhenUserValueIsNotEmpty() {
+
+ $instance = new AllowsPatternValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'abc/e' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testGetShortWikiText() {
+
+ $allowsPatternValueParser = $this->getMockBuilder( '\SMW\DataValues\ValueParsers\AllowsPatternValueParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $allowsPatternValueParser->expects( $this->any() )
+ ->method( 'parse' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( $allowsPatternValueParser ) );
+
+ $dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $this->constraintValueValidator ) );
+
+ $instance = new AllowsPatternValue();
+ $instance->setOption( 'smwgDVFeatures', SMW_DV_PVAP );
+
+ $instance->setDataValueServiceFactory(
+ $dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'abc/e' );
+
+ $this->assertContains(
+ 'Smw_allows_pattern',
+ $instance->getShortWikiText()
+ );
+ }
+
+ public function testGetShortHtmlText() {
+
+ $allowsPatternValueParser = $this->getMockBuilder( '\SMW\DataValues\ValueParsers\AllowsPatternValueParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $allowsPatternValueParser->expects( $this->any() )
+ ->method( 'parse' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( $allowsPatternValueParser ) );
+
+ $dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $this->constraintValueValidator ) );
+
+ $instance = new AllowsPatternValue();
+ $instance->setOption( 'smwgDVFeatures', SMW_DV_PVAP );
+
+ $instance->setDataValueServiceFactory(
+ $dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'abc/e' );
+
+ $this->assertContains(
+ 'Smw_allows_pattern',
+ $instance->getShortHtmlText()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/BooleanValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/BooleanValueTest.php
new file mode 100644
index 00000000..f0ed6c3b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/BooleanValueTest.php
@@ -0,0 +1,205 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\BooleanValue;
+use SMW\Localizer;
+
+/**
+ * @covers \SMW\DataValues\BooleanValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class BooleanValueTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ BooleanValue::class,
+ new BooleanValue()
+ );
+ }
+
+ public function testGetBoolean() {
+
+ $instance = new BooleanValue();
+
+ $this->assertFalse(
+ $instance->getBoolean()
+ );
+
+ $instance->setUserValue( 'true' );
+
+ $this->assertTrue(
+ $instance->getBoolean()
+ );
+ }
+
+ public function testParseUserValueOnSpecificPageContentLanguage() {
+
+ $language = Localizer::getInstance()->getLanguage( 'ja' );
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new BooleanValue();
+
+ $instance->setContextPage( $subject );
+ $instance->setUserValue( '真' );
+
+ $this->assertTrue(
+ $instance->getBoolean()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getWikiValue()
+ );
+ }
+
+ public function testGetShortWikiTextForLocalizedOutputFormat() {
+
+ $instance = new BooleanValue();
+
+ $instance->setUserValue( 'true' );
+ $instance->setOutputFormat( 'LOCL@fr' );
+
+ $this->assertEquals(
+ 'vrai',
+ $instance->getShortWikiText()
+ );
+ }
+
+ public function testGetShortHTMLTextForLocalizedOutputFormat() {
+
+ $instance = new BooleanValue();
+
+ $instance->setUserValue( 'true' );
+ $instance->setOutputFormat( 'LOCL@fr' );
+
+ $this->assertEquals(
+ 'vrai',
+ $instance->getShortHTMLText()
+ );
+ }
+
+ public function testGetLongWikiTextForLocalizedOutputFormat() {
+
+ $instance = new BooleanValue();
+
+ $instance->setUserValue( 'true' );
+ $instance->setOutputFormat( 'LOCL@fr' );
+
+ $this->assertEquals(
+ 'vrai',
+ $instance->getLongWikiText()
+ );
+ }
+
+ public function testGetLongWikiText_PlainFormatter() {
+
+ $instance = new BooleanValue();
+
+ $instance->setUserValue( 'true' );
+ $instance->setOutputFormat( '-' );
+
+ $this->assertEquals(
+ 'true',
+ $instance->getLongWikiText()
+ );
+ }
+
+ public function testGetLongWikiText_NumFormatter() {
+
+ $instance = new BooleanValue();
+
+ $instance->setUserValue( 'true' );
+ $instance->setOutputFormat( 'num' );
+
+ $this->assertEquals(
+ 1,
+ $instance->getLongWikiText()
+ );
+
+ $instance->setUserValue( 'false' );
+ $instance->setOutputFormat( 'num' );
+
+ $this->assertEquals(
+ 0,
+ $instance->getLongWikiText()
+ );
+ }
+
+ public function testGetLongWikiText_TickFormatter() {
+
+ $instance = new BooleanValue();
+
+ $instance->setUserValue( 'true' );
+ $instance->setOutputFormat( 'tick' );
+
+ $this->assertEquals(
+ '✓',
+ $instance->getLongWikiText()
+ );
+
+ $instance->setUserValue( 'false' );
+ $instance->setOutputFormat( 'tick' );
+
+ $this->assertEquals(
+ '✕',
+ $instance->getLongWikiText()
+ );
+ }
+
+ public function testGetLongWikiText_xFormatter() {
+
+ $instance = new BooleanValue();
+
+ $instance->setUserValue( 'true' );
+ $instance->setOutputFormat( 'x' );
+
+ $this->assertEquals(
+ '<span style="font-family: sans-serif; ">X</span>',
+ $instance->getLongWikiText()
+ );
+
+ $instance->setUserValue( 'false' );
+ $instance->setOutputFormat( 'x' );
+
+ $this->assertEquals(
+ '&nbsp;',
+ $instance->getLongWikiText()
+ );
+ }
+
+ public function testRecognizeCanonicalForm() {
+
+ $instance = new BooleanValue();
+ $instance->setOption( BooleanValue::OPT_CONTENT_LANGUAGE, 'el' );
+
+ $instance->setUserValue( 'true' );
+
+ $this->assertEquals(
+ 'true',
+ $instance->getShortWikiText()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ErrorMsgTextValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ErrorMsgTextValueTest.php
new file mode 100644
index 00000000..ada99376
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ErrorMsgTextValueTest.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ErrorMsgTextValue;
+
+/**
+ * @covers \SMW\DataValues\ErrorMsgTextValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ErrorMsgTextValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+
+ protected function setUp() {
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ErrorMsgTextValue',
+ new ErrorMsgTextValue()
+ );
+ }
+
+ public function testErrorOnEmptyUserValue() {
+
+ $instance = new ErrorMsgTextValue();
+ $instance->setUserValue( '' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testShortWikiText() {
+
+ $instance = new ErrorMsgTextValue();
+ $instance->setOption( ErrorMsgTextValue::OPT_USER_LANGUAGE, 'en' );
+ $instance->setUserValue( '[2,"smw-datavalue-uniqueness-constraint-error","Has Url","http:\/\/loremipsum.org\/2","Lorem ipsum\/2"]' );
+
+ $this->assertContains(
+ "''http://loremipsum.org/2''",
+ $instance->getShortWikiText( true )
+ );
+
+ $this->assertContains(
+ "''http://loremipsum.org/2''",
+ $instance->getShortWikiText( null )
+ );
+
+ $this->assertNotContains(
+ '<a rel="nofollow" class="external free" href="http://loremipsum.org/2">http://loremipsum.org/2</a>',
+ $instance->getShortWikiText( true )
+ );
+
+ $this->assertNotContains(
+ '<a rel="nofollow" class="external free" href="http://loremipsum.org/2">http://loremipsum.org/2</a>',
+ $instance->getShortWikiText( null )
+ );
+ }
+
+ /**
+ * @dataProvider textProvider
+ */
+ public function testValueOutput( $text, $expected ) {
+
+ $dataItem = $this->dataItemFactory->newDIBlob( $text );
+
+ $instance = new ErrorMsgTextValue();
+ $instance->setDataItem( $dataItem );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getWikiValue()
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getShortWikiText()
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getShortHTMLText()
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getLongWikiText()
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getLongHTMLText()
+ );
+ }
+
+ public function textProvider() {
+
+ $provider[] = [
+ 'Foo',
+ 'Foo'
+ ];
+
+ $provider[] = [
+ '[2,"Foo"]',
+ 'Foo'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalFormatterUriValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalFormatterUriValueTest.php
new file mode 100644
index 00000000..ef39d298
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalFormatterUriValueTest.php
@@ -0,0 +1,169 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\ExternalFormatterUriValue;
+
+/**
+ * @covers \SMW\DataValues\ExternalFormatterUriValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ExternalFormatterUriValueTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ExternalFormatterUriValue::class,
+ new ExternalFormatterUriValue()
+ );
+ }
+
+ public function testTryToParseUserValueOnInvalidUrlFormat() {
+
+ $instance = new ExternalFormatterUriValue();
+ $instance->setUserValue( 'foo' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testTryToParseUserValueOnMissingPlaceholder() {
+
+ $instance = new ExternalFormatterUriValue();
+ $instance->setUserValue( 'http://example.org' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ /**
+ * @dataProvider uriProvider
+ */
+ public function testGetFormattedUri( $uri, $replacement, $expected ) {
+
+ $instance = new ExternalFormatterUriValue();
+ $instance->setUserValue( $uri );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getUriWithPlaceholderSubstitution( $replacement )
+ );
+ }
+
+ public function uriProvider() {
+
+ $provider[] = [
+ 'http://example.org/$1',
+ 'foo',
+ 'http://example.org/foo'
+ ];
+
+ $provider[] = [
+ 'http://example.org/$1#Bar<>',
+ 'foo',
+ 'http://example.org/foo#Bar%3C%3E'
+ ];
+
+ $provider[] = [
+ 'urn:abc:names:def:foo:dtd:xml:$1',
+ 'foo',
+ 'urn:abc:names:def:foo:dtd:xml:foo'
+ ];
+
+ // $provider[] = array(
+ // 'abc:$1',
+ // 'foo',
+ // 'http://example.org/foo'
+ // );
+
+ $provider[] = [
+ 'ftp://ftp.is.co.za.example.org/rfc/$1.txt',
+ 'foo',
+ 'ftp://ftp.is.co.za.example.org/rfc/foo.txt'
+ ];
+
+ $provider[] = [
+ 'gopher://spinaltap.micro.umn.example.edu/00/Weather/California/$1',
+ 'foo',
+ 'gopher:spinaltap.micro.umn.example.edu/00/Weather/California/foo'
+ ];
+
+ $provider[] = [
+ 'http://www.math.uio.no.example.net/faq/compression-faq/$1',
+ 'foo',
+ 'http://www.math.uio.no.example.net/faq/compression-faq/foo'
+ ];
+
+ $provider[] = [
+ 'mailto:$1@ifi.unizh.example.gov',
+ 'foo',
+ 'mailto:foo@ifi.unizh.example.gov'
+ ];
+
+ $provider[] = [
+ 'news:comp.$1.www.servers.unix',
+ 'foo',
+ 'news:comp.foo.www.servers.unix'
+ ];
+
+ $provider[] = [
+ 'telnet://melvyl.ucop.example.edu/$1',
+ 'foo',
+ 'telnet:melvyl.ucop.example.edu/foo'
+ ];
+
+ $provider[] = [
+ 'ldap://[2001:db8::7]/c=$1?objectClass?one',
+ 'foo',
+ 'ldap:%5B2001:db8::7%5D/c=foo?objectClass?one'
+ ];
+
+ $provider[] = [
+ 'mailto:$1.Doe@example.com',
+ 'foo',
+ 'mailto:foo.Doe@example.com'
+ ];
+
+ $provider[] = [
+ 'tel:+1-816-555-1212',
+ 'foo',
+ ''
+ ];
+
+ $provider[] = [
+ 'telnet://192.0.2.16:80/$1',
+ 'foo',
+ 'telnet:192.0.2.16:80/foo'
+ ];
+
+ $provider[] = [
+ 'urn:oasis:names:specification:docbook:dtd:xml:$1',
+ 'foo',
+ 'urn:oasis:names:specification:docbook:dtd:xml:foo'
+ ];
+
+ // https://phabricator.wikimedia.org/T160281
+ $provider[] = [
+ 'http://foo/bar/$1',
+ 'W%D6LLEKLA01',
+ 'http://foo/bar/W%D6LLEKLA01'
+ ];
+
+ // #3386
+ $provider[] = [
+ 'http://foo/bar/$1',
+ 'A/B/C',
+ 'http://foo/bar/A/B/C'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalIdentifierValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalIdentifierValueTest.php
new file mode 100644
index 00000000..63273da1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ExternalIdentifierValueTest.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\DataValues\ExternalIdentifierValue;
+use SMW\PropertySpecificationLookup;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\ExternalIdentifierValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ExternalIdentifierValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( PropertySpecificationLookup::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $externalFormatterUriValue = $this->getMockBuilder( '\SMW\DataValues\ExternalFormatterUriValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getPropertySpecificationLookup' )
+ ->will( $this->returnValue( $this->propertySpecificationLookup ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getDataValueFactory' )
+ ->will( $this->returnValue( DataValueFactory::getInstance() ) );
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ExternalIdentifierValue::class,
+ new ExternalIdentifierValue()
+ );
+ }
+
+ public function testGetShortWikiText() {
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'getExternalFormatterUri' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIUri( 'http', 'example.org/$1' ) ) );
+
+ $instance = new ExternalIdentifierValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+
+ $instance->setUserValue( 'foo' );
+ $instance->setProperty( $this->dataItemFactory->newDIProperty( 'Bar' ) );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertEquals(
+ '<span class="plainlinks smw-eid">[http://example.org/foo foo]</span>',
+ $instance->getShortWikiText( 'linker' )
+ );
+ }
+
+ public function testGetShortWikiText_Nowiki() {
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'getExternalFormatterUri' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIUri( 'http', 'example.org/$1' ) ) );
+
+ $instance = new ExternalIdentifierValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+
+ $instance->setUserValue( 'foo' );
+ $instance->setOutputFormat( 'nowiki' );
+ $instance->setProperty( $this->dataItemFactory->newDIProperty( 'Bar' ) );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertEquals(
+ '<span class="plainlinks smw-eid">http&#58;//example.org/foo</span>',
+ $instance->getShortWikiText( 'linker' )
+ );
+ }
+
+ public function testGetShortHTMLText() {
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'getExternalFormatterUri' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIUri( 'http', 'example.org/$1' ) ) );
+
+ $instance = new ExternalIdentifierValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+
+ $instance->setUserValue( 'foo' );
+ $instance->setProperty( $this->dataItemFactory->newDIProperty( 'Bar' ) );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getShortHTMLText()
+ );
+
+ $this->assertEquals(
+ '<a href="http://example.org/foo" target="_blank">foo</a>',
+ $instance->getShortHTMLText( 'linker' )
+ );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testTryToGetShortHTMLTextWithLinkerOnMissingFormatterUri() {
+
+ $instance = new ExternalIdentifierValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+
+ $instance->setUserValue( 'foo' );
+ $instance->setProperty( $this->dataItemFactory->newDIProperty( 'Bar' ) );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getShortHTMLText()
+ );
+
+ $instance->getShortHTMLText( 'linker' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ImportValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ImportValueTest.php
new file mode 100644
index 00000000..892ac2d0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ImportValueTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\ImportValue;
+use SMW\DataValues\ValueParsers\ImportValueParser;
+
+/**
+ * @covers \SMW\DataValues\ImportValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ImportValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $mediaWikiNsContentReader = $this->getMockBuilder( '\SMW\MediaWiki\MediaWikiNsContentReader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( new ImportValueParser( $mediaWikiNsContentReader ) ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ImportValue',
+ new ImportValue()
+ );
+
+ // FIXME Legacy naming remove in 3.x
+ $this->assertInstanceOf(
+ '\SMWImportValue',
+ new ImportValue()
+ );
+ }
+
+ public function testErrorForInvalidUserValue() {
+
+ $instance = new ImportValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+
+ $instance->setUserValue( 'FooBar' );
+
+ $this->assertEquals(
+ 'FooBar',
+ $instance->getWikiValue()
+ );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/InfoLinksProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/InfoLinksProviderTest.php
new file mode 100644
index 00000000..93b297b4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/InfoLinksProviderTest.php
@@ -0,0 +1,251 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\DataValues\InfoLinksProvider;
+use SMW\DataValues\StringValue;
+use SMW\Message;
+use SMW\Tests\TestEnvironment;
+use SMWNumberValue as NumberValue;
+
+/**
+ * @covers \SMW\DataValues\InfoLinksProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class InfoLinksProviderTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $dataValueServiceFactory;
+ private $propertySpecificationLookup;
+ private $dataValueFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ InfoLinksProvider::class,
+ new InfoLinksProvider( $dataValue, $this->propertySpecificationLookup )
+ );
+ }
+
+ public function testGetInfolinkTextOnNumberValue() {
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getSpecification' )
+ ->will( $this->returnValue( [] ) );
+
+ $numberValue = $this->dataValueFactory->newDataValueByType( NumberValue::TYPE_ID );
+
+ $numberValue->setOption( 'user.language', 'en' );
+ $numberValue->setOption( 'content.language', 'en' );
+
+ $numberValue->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $numberValue->setUserValue( '1000.42' );
+
+ $instance = new InfoLinksProvider( $numberValue, $this->propertySpecificationLookup );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'newInfoLinksProvider' )
+ ->will( $this->returnValue( $instance ) );
+
+ $this->assertContains(
+ '/:Foo/1000.42|+]]</span>',
+ $instance->getInfolinkText( SMW_OUTPUT_WIKI )
+ );
+
+ $this->assertContains(
+ '/:Foo/1000.42">+</a></span>',
+ $instance->getInfolinkText( SMW_OUTPUT_HTML )
+ );
+ }
+
+ public function testGetInfolinkTextOnStringValue() {
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getSpecification' )
+ ->will( $this->returnValue( [] ) );
+
+ $stringValue = $this->dataValueFactory->newDataValueByType( StringValue::TYPE_ID );
+
+ $stringValue->setOption( 'user.language', 'en' );
+ $stringValue->setOption( 'content.language', 'en' );
+
+ $stringValue->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $stringValue->setUserValue( 'Text with :: content' );
+
+ $instance = new InfoLinksProvider( $stringValue, $this->propertySpecificationLookup );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'newInfoLinksProvider' )
+ ->will( $this->returnValue( $instance ) );
+
+ $this->assertContains(
+ '/:Foo/Text-20with-20-2D3A-2D3A-20content|+]]</span>',
+ $instance->getInfolinkText( SMW_OUTPUT_WIKI )
+ );
+
+ $this->assertContains(
+ '/:Foo/Text-20with-20-2D3A-2D3A-20content">+</a></span>',
+ $instance->getInfolinkText( SMW_OUTPUT_HTML )
+ );
+ }
+
+ public function testGetInfolinkTextOnSobValue() {
+
+ $stringValidator = $this->testEnvironment->newValidatorFactory()->newStringValidator();
+
+ $sobValue = $this->dataValueFactory->newDataValueByType( '__sob' );
+ $sobValue->setUserValue( 'Text with :: content' );
+
+ $instance = new InfoLinksProvider( $sobValue, $this->propertySpecificationLookup );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'newInfoLinksProvider' )
+ ->will( $this->returnValue( $instance ) );
+
+ $stringValidator->assertThatStringContains(
+ '<span class="smwbrowse">[[.*/:Text-20with-20::-20content|+]]</span>',
+ $instance->getInfolinkText( SMW_OUTPUT_WIKI )
+ );
+
+ $stringValidator->assertThatStringContains(
+ '<span class="smwbrowse"><a .*/:Text-20with-20::-20content" title=".*/:Text-20with-20::-20content">+</a></span>',
+ $instance->getInfolinkText( SMW_OUTPUT_HTML )
+ );
+ }
+
+ public function testGetInfolinkTextOnTimeValueWithoutLocalizedOutput() {
+
+ $timeValue = $this->dataValueFactory->newDataValueByType( '_dat' );
+
+ $timeValue->setOption( $timeValue::OPT_USER_LANGUAGE, 'fr' );
+ $timeValue->setOption( $timeValue::OPT_CONTENT_LANGUAGE, 'en' );
+
+ // Forcibly set an output
+ $timeValue->setOutputFormat( 'LOCL' );
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_dat' );
+
+ $timeValue->setProperty(
+ $property
+ );
+
+ $timeValue->setDataItem(
+ $this->dataItemFactory->newDITime( 1, 1970, 12, 12 )
+ );
+
+ $instance = new InfoLinksProvider( $timeValue, $this->propertySpecificationLookup );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'newInfoLinksProvider' )
+ ->will( $this->returnValue( $instance ) );
+
+ $this->assertContains(
+ '/:Foo/12-20December-201970|+]]</span>',
+ $instance->getInfolinkText( SMW_OUTPUT_WIKI )
+ );
+
+ $this->assertContains(
+ '/:Foo/12-20December-201970">+</a></span>',
+ $instance->getInfolinkText( SMW_OUTPUT_HTML )
+ );
+ }
+
+ public function testGetInfolinkTextOnStringValueWithServiceLinks() {
+
+ $service = 'testGetInfolinkTextOnStringValueWithServiceLinks';
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getSpecification' )
+ ->will( $this->returnValue( [
+ $this->dataItemFactory->newDIBlob( $service ) ] ) );
+
+ // Manipulating the Message cache is a hack!!
+ $parameters = [
+ "smw_service_" . $service,
+ 'Bar'
+ ];
+
+ Message::getCache()->save(
+ Message::getHash( $parameters, Message::TEXT, Message::CONTENT_LANGUAGE ),
+ 'SERVICELINK-A|SERVICELINK-B'
+ );
+
+ $stringValue = $this->dataValueFactory->newDataValueByType( StringValue::TYPE_ID );
+
+ $stringValue->setOption( StringValue::OPT_USER_LANGUAGE, 'en' );
+ $stringValue->setOption( StringValue::OPT_CONTENT_LANGUAGE, 'en' );
+
+ $stringValue->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $stringValue->setUserValue( 'Bar' );
+
+ $instance = new InfoLinksProvider( $stringValue, $this->propertySpecificationLookup );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'newInfoLinksProvider' )
+ ->will( $this->returnValue( $instance ) );
+
+ $this->assertContains(
+ '<span class="smwttcontent">[SERVICELINK-B SERVICELINK-A]</span>',
+ $instance->getInfolinkText( SMW_OUTPUT_WIKI )
+ );
+
+ $this->assertContains(
+ '<span class="smwttcontent"><a href="SERVICELINK-B">SERVICELINK-A</a></span>',
+ $instance->getInfolinkText( SMW_OUTPUT_HTML )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/KeywordValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/KeywordValueTest.php
new file mode 100644
index 00000000..500463cc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/KeywordValueTest.php
@@ -0,0 +1,163 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\DataValues\KeywordValue;
+use SMW\PropertySpecificationLookup;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\KeywordValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class KeywordValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( PropertySpecificationLookup::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $externalFormatterUriValue = $this->getMockBuilder( '\SMW\DataValues\ExternalFormatterUriValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getPropertySpecificationLookup' )
+ ->will( $this->returnValue( $this->propertySpecificationLookup ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getDataValueFactory' )
+ ->will( $this->returnValue( DataValueFactory::getInstance() ) );
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ KeywordValue::class,
+ new KeywordValue()
+ );
+ }
+
+ public function testErrorWhenLengthExceedsLimit() {
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getSpecification' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new KeywordValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+
+ $instance->setUserValue( 'LTVCLTVCSGFzLTIwa2V5d29yZC0yMHRlc3Q6OnRFc3QtMjAyLTVELTVEL2Zvcm1hdD1jYXRlZ29yeS8tM0ZIYXMtMjBkZXNjcmlwdGlvbgLTVCLTVCSGFzLTIwa2V5d29yZC0yMHRlc3Q6OnRFc3QtMjAyLTVELTVEL2Zvcm1hdD1jYXRlZ29yeS8tM0ZIYXMtMjBkZXNjcmlwdGlvbgLTVCLTVCSGFzLTIwaLTVCLTVCSGFzLTIwa..........' );
+ $instance->setProperty( $this->dataItemFactory->newDIProperty( 'Bar' ) );
+
+ $this->assertEquals(
+ '',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertContains(
+ 'smw-datavalue-keyword-maximum-length',
+ implode( ', ', $instance->getErrors() )
+ );
+ }
+
+ public function testGetShortWikiText_WithoutLink() {
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getSpecification' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new KeywordValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+
+ $instance->setUserValue( 'foo' );
+ $instance->setProperty( $this->dataItemFactory->newDIProperty( 'Bar' ) );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getShortWikiText( 'linker' )
+ );
+ }
+
+ public function testGetShortWikiText_WithLink() {
+
+ $data = json_encode(
+ [
+ 'type' => 'LINK_FORMAT_SCHEMA',
+ 'rule' => [ 'link_to' => 'SPECIAL_SEARCH_BY_PROPERTY' ]
+ ]
+ );
+
+ $this->propertySpecificationLookup->expects( $this->at( 0 ) )
+ ->method( 'getSpecification' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_FORMAT_SCHEMA' ) ) )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIWikiPage( 'Bar', SMW_NS_SCHEMA ) ] ) );
+
+ $this->propertySpecificationLookup->expects( $this->at( 1 ) )
+ ->method( 'getSpecification' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_SCHEMA_DEF' ) ) )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBlob( $data ) ] ) );
+
+ $instance = new KeywordValue();
+ $instance->setDataValueServiceFactory( $this->dataValueServiceFactory );
+ $instance->setOption( KeywordValue::OPT_COMPACT_INFOLINKS, true );
+
+ $instance->setUserValue( 'foo' );
+ $instance->setProperty( $this->dataItemFactory->newDIProperty( 'Bar' ) );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertContains(
+ '[[:Special:SearchByProperty/cl:OkJhci9mb28|foo]]',
+ $instance->getShortWikiText( 'linker' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/LanguageCodeValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/LanguageCodeValueTest.php
new file mode 100644
index 00000000..61a16179
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/LanguageCodeValueTest.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\LanguageCodeValue;
+
+/**
+ * @covers \SMW\DataValues\LanguageCodeValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class LanguageCodeValueTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\LanguageCodeValue',
+ new LanguageCodeValue()
+ );
+ }
+
+ public function testHasErrorForMissingLanguageCode() {
+
+ $instance = new LanguageCodeValue();
+ $instance->setUserValue( '' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testHasErrorForInvalidLanguageCode() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( 'Skipping because `Language::isKnownLanguageTag` is not supported on 1.19' );
+ }
+
+ $instance = new LanguageCodeValue();
+ $instance->setUserValue( '-Foo' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testNormalizationOnLanguageCodeOccurs() {
+
+ $mixedCase = new LanguageCodeValue();
+ $mixedCase->setUserValue( 'eN' );
+
+ $upperCase = new LanguageCodeValue();
+ $upperCase->setUserValue( 'EN' );
+
+ $this->assertEquals(
+ $mixedCase->getDataItem(),
+ $upperCase->getDataItem()
+ );
+
+ $this->assertEquals(
+ 'en',
+ $mixedCase->getDataItem()->getString()
+ );
+
+ $this->assertEquals(
+ 'en',
+ $upperCase->getDataItem()->getString()
+ );
+ }
+
+ public function testInvalidLanguageCode() {
+
+ $instance = new LanguageCodeValue();
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertContains(
+ '[2,"smw-datavalue-languagecode-invalid","foo"]',
+ $instance->getDataItem()->getString()
+ );
+ }
+
+ public function testInvalidLanguageCodeIsAllowedInQueryContext() {
+
+ $instance = new LanguageCodeValue();
+ $instance->setOption( LanguageCodeValue::OPT_QUERY_CONTEXT, true );
+
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getDataItem()->getString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/MonolingualTextValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/MonolingualTextValueTest.php
new file mode 100644
index 00000000..d402f33a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/MonolingualTextValueTest.php
@@ -0,0 +1,259 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\MonolingualTextValue;
+use SMW\DataValues\ValueFormatters\MonolingualTextValueFormatter;
+use SMW\DataValues\ValueParsers\MonolingualTextValueParser;
+
+/**
+ * @covers \SMW\DataValues\MonolingualTextValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class MonolingualTextValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( new MonolingualTextValueParser() ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\MonolingualTextValue',
+ new MonolingualTextValue()
+ );
+ }
+
+ public function testErrorForMissingLanguageCode() {
+
+ $instance = new MonolingualTextValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setOption( 'smwgDVFeatures', SMW_DV_MLTV_LCODE );
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testNoErrorForMissingLanguageCodeWhenFeatureIsDisabled() {
+
+ $instance = new MonolingualTextValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setOption( 'smwgDVFeatures', false );
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testErrorForInvalidLanguageCode() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( 'Skipping because `Language::isKnownLanguageTag` is not supported on 1.19' );
+ }
+
+ $instance = new MonolingualTextValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'Foo@foobar' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testValidParsableUserValue() {
+
+ $instance = new MonolingualTextValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'Foo@en' );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $instance->getDataItem()
+ );
+
+ foreach ( $instance->getDataItems() as $dataItem ) {
+ $this->assertInstanceOf(
+ '\SMWDIBlob',
+ $dataItem
+ );
+ }
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getTextValueByLanguage( 'en' )->getDataItem()->getString()
+ );
+ }
+
+ public function testTryToGetTextValueByLanguageForUnrecognizedLanguagCode() {
+
+ $instance = new MonolingualTextValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'Foo@en' );
+
+ $this->assertNull(
+ $instance->getTextValueByLanguage( 'bar' )
+ );
+ }
+
+ public function testGetWikiValueForValidMonolingualTextValue() {
+
+ $instance = new MonolingualTextValue();
+
+ $monolingualTextValueFormatter = new MonolingualTextValueFormatter();
+ $monolingualTextValueFormatter->setDataValue( $instance );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $monolingualTextValueFormatter ) );
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'Foo@en' );
+
+ $this->assertEquals(
+ 'Foo@en',
+ $instance->getWikiValue()
+ );
+ }
+
+ public function testGetWikiValueForInvalidMonolingualTextValue() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( 'Skipping because `Language::isKnownLanguageTag` is not supported on 1.19' );
+ }
+
+ $instance = new MonolingualTextValue();
+
+ $monolingualTextValueFormatter = new MonolingualTextValueFormatter();
+ $monolingualTextValueFormatter->setDataValue( $instance );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $monolingualTextValueFormatter ) );
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'Foo@foobar' );
+
+ $this->assertContains(
+ 'class="smw-highlighter" data-type="4"',
+ $instance->getWikiValue()
+ );
+ }
+
+ public function testGetProperties() {
+
+ $instance = new MonolingualTextValue();
+ $properties = $instance->getPropertyDataItems();
+
+ $this->assertEquals(
+ '_TEXT',
+ $properties[0]->getKey()
+ );
+
+ $this->assertEquals(
+ '_LCODE',
+ $properties[1]->getKey()
+ );
+ }
+
+ public function testToArray() {
+
+ $instance = new MonolingualTextValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'Foo@en' );
+
+ $this->assertEquals(
+ [
+ '_TEXT' => 'Foo',
+ '_LCODE' => 'en'
+ ],
+ $instance->toArray()
+ );
+ }
+
+ public function testToString() {
+
+ $instance = new MonolingualTextValue();
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'Foo@en' );
+
+ $this->assertSame(
+ 'Foo@en',
+ $instance->toString()
+ );
+ }
+
+ public function testGetTextWithLanguageTag() {
+
+ $instance = new MonolingualTextValue();
+
+ $this->assertSame(
+ 'foo@zh-Hans',
+ $instance->getTextWithLanguageTag( 'foo', 'zh-hans' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/IntlNumberFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/IntlNumberFormatterTest.php
new file mode 100644
index 00000000..326ed465
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/IntlNumberFormatterTest.php
@@ -0,0 +1,348 @@
+<?php
+
+namespace SMW\Tests\DataValues\Number;
+
+use Language;
+use SMW\DataValues\Number\IntlNumberFormatter;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\Number\IntlNumberFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class IntlNumberFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ IntlNumberFormatter::class,
+ new IntlNumberFormatter( 10000 )
+ );
+
+ $this->assertInstanceOf(
+ IntlNumberFormatter::class,
+ IntlNumberFormatter::getInstance()
+ );
+ }
+
+ /**
+ * @dataProvider numberProvider
+ */
+ public function testLocalizedFormattedNumber( $maxNonExpNumber, $number, $userLanguage, $contentLanguage, $expected ) {
+
+ $instance = new IntlNumberFormatter( $maxNonExpNumber );
+
+ $instance->setOption( IntlNumberFormatter::USER_LANGUAGE, $userLanguage );
+ $instance->setOption( IntlNumberFormatter::CONTENT_LANGUAGE, $contentLanguage );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $number )
+ );
+ }
+
+ public function testZeroPadding() {
+
+ $expected = '1000(foo)42';
+
+ $instance = new IntlNumberFormatter( 10000 );
+
+ // #2797
+ $instance->setOption( IntlNumberFormatter::DECIMAL_SEPARATOR, '(foo)' );
+ $instance->setOption( IntlNumberFormatter::THOUSANDS_SEPARATOR, '' );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( 1000.42 )
+ );
+ }
+
+ /**
+ * @dataProvider unformattedNumberByPrecisionProvider
+ */
+ public function testGetUnformattedNumberByPrecision( $maxNonExpNumber, $number, $precision, $userLanguage, $contentLanguage, $expected ) {
+
+ $instance = new IntlNumberFormatter( $maxNonExpNumber );
+
+ $instance->setOption( IntlNumberFormatter::USER_LANGUAGE, $userLanguage );
+ $instance->setOption( IntlNumberFormatter::CONTENT_LANGUAGE, $contentLanguage );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $number, $precision, IntlNumberFormatter::VALUE_FORMAT )
+ );
+ }
+
+ public function testCompareFloatValue() {
+
+ $instance = new IntlNumberFormatter( 1000 );
+
+ $instance->setOption( IntlNumberFormatter::USER_LANGUAGE, 'en' );
+ $instance->setOption( IntlNumberFormatter::CONTENT_LANGUAGE, 'en' );
+
+ $this->assertSame(
+ $instance->format( 100.0, false, IntlNumberFormatter::VALUE_FORMAT ),
+ $instance->format( 100, false, IntlNumberFormatter::VALUE_FORMAT )
+ );
+ }
+
+ /**
+ * @dataProvider separatorProvider
+ */
+ public function testgetSeparatorByLanguage( $type, $locale, $userLanguage, $contentLanguage, $expected ) {
+
+ $instance = new IntlNumberFormatter( 10000000 );
+
+ $instance->setOption( IntlNumberFormatter::USER_LANGUAGE, $userLanguage );
+ $instance->setOption( IntlNumberFormatter::CONTENT_LANGUAGE, $contentLanguage );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getSeparatorByLanguage( $type, $locale )
+ );
+ }
+
+ public function testCustomSeparator() {
+
+ $instance = new IntlNumberFormatter( 10000000 );
+
+ $instance->setOption( IntlNumberFormatter::DECIMAL_SEPARATOR, 'FOO' );
+ $instance->setOption( IntlNumberFormatter::THOUSANDS_SEPARATOR, 'BAR' );
+
+ $this->assertEquals(
+ 'FOO',
+ $instance->getSeparatorByLanguage( IntlNumberFormatter::DECIMAL_SEPARATOR, 'zzz' )
+ );
+
+ $this->assertEquals(
+ 'BAR',
+ $instance->getSeparatorByLanguage( IntlNumberFormatter::THOUSANDS_SEPARATOR, 'zzz' )
+ );
+ }
+
+ public function testTryTogetSeparatorByLanguageOnInvalidTypeThrowsException() {
+
+ $instance = new IntlNumberFormatter( 10000000 );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->getSeparatorByLanguage( 'Foo' );
+ }
+
+ public function numberProvider() {
+
+ $provider[] = [
+ 10000,
+ 1000,
+ 'en',
+ 'en',
+ '1,000'
+ ];
+
+ $provider[] = [
+ 10000,
+ 1000.42,
+ 'en',
+ 'en',
+ '1,000.42'
+ ];
+
+ $provider[] = [
+ 10000,
+ 1000000,
+ 'en',
+ 'en',
+ '1.0e+6'
+ ];
+
+ $provider[] = [
+ 10000000,
+ 1000000,
+ 'en',
+ 'en',
+ '1,000,000'
+ ];
+
+ return $provider;
+ }
+
+ public function unformattedNumberByPrecisionProvider() {
+
+ $provider['un.1'] = [
+ 10000,
+ 1000,
+ 2,
+ 'en',
+ 'en',
+ '1000.00'
+ ];
+
+ $provider['un.2'] = [
+ 10000,
+ 1000.42,
+ 3,
+ 'en',
+ 'en',
+ '1000.420'
+ ];
+
+ $provider['un.3'] = [
+ 10000,
+ 1000000,
+ 0,
+ 'en',
+ 'en',
+ '1000000'
+ ];
+
+ $provider['un.4'] = [
+ 10000000,
+ 1000000,
+ 2,
+ 'en',
+ 'en',
+ '1000000.00'
+ ];
+
+ $provider['un.5'] = [
+ 10000000,
+ 1000000,
+ false,
+ 'en',
+ 'en',
+ '1000000'
+ ];
+
+ $provider['un.6'] = [
+ 10000000,
+ 312.23545555,
+ false,
+ 'en',
+ 'en',
+ '312.23545555'
+ ];
+
+ $provider['un.7'] = [
+ 10000000,
+ 312.23545555,
+ 6,
+ 'en',
+ 'en',
+ '312.235456'
+ ];
+
+ $provider['un.8'] = [
+ 10000000,
+ 312.23545555,
+ 9,
+ 'en',
+ 'en',
+ '312.235455550'
+ ];
+
+ $provider['un.9'] = [
+ 10000000,
+ 312.23545555,
+ null,
+ 'en',
+ 'en',
+ '312.235455550'
+ ];
+
+ $provider['un.10'] = [
+ 10000000,
+ 1.334e-13,
+ false,
+ 'en',
+ 'en',
+ '1.334e-13'
+ ];
+
+ $provider['un.11'] = [
+ 10000000,
+ 1.334e-13,
+ false,
+ 'en',
+ 'fr',
+ '1,334e-13'
+ ];
+
+ return $provider;
+ }
+
+ public function separatorProvider() {
+
+ $provider['1.en'] = [
+ IntlNumberFormatter::DECIMAL_SEPARATOR,
+ IntlNumberFormatter::USER_LANGUAGE,
+ 'en',
+ 'en',
+ '.'
+ ];
+
+ $provider['2.en'] = [
+ IntlNumberFormatter::THOUSANDS_SEPARATOR,
+ IntlNumberFormatter::USER_LANGUAGE,
+ 'en',
+ 'en',
+ ','
+ ];
+
+ $provider['3.en'] = [
+ IntlNumberFormatter::DECIMAL_SEPARATOR,
+ IntlNumberFormatter::CONTENT_LANGUAGE,
+ 'en',
+ 'en',
+ '.'
+ ];
+
+ $provider['4.en'] = [
+ IntlNumberFormatter::THOUSANDS_SEPARATOR,
+ IntlNumberFormatter::CONTENT_LANGUAGE,
+ 'en',
+ 'en',
+ ','
+ ];
+
+ $provider['5.fr'] = [
+ IntlNumberFormatter::DECIMAL_SEPARATOR,
+ IntlNumberFormatter::USER_LANGUAGE,
+ 'fr',
+ 'en',
+ ','
+ ];
+
+ $provider['6.fr'] = [
+ IntlNumberFormatter::THOUSANDS_SEPARATOR,
+ IntlNumberFormatter::USER_LANGUAGE,
+ 'fr',
+ 'en',
+ ' '
+ ];
+
+ $provider['7.fr'] = [
+ IntlNumberFormatter::DECIMAL_SEPARATOR,
+ IntlNumberFormatter::CONTENT_LANGUAGE,
+ 'fr',
+ 'fr',
+ ','
+ ];
+
+ $provider['8.fr'] = [
+ IntlNumberFormatter::THOUSANDS_SEPARATOR,
+ IntlNumberFormatter::CONTENT_LANGUAGE,
+ 'fr',
+ 'fr',
+ ' '
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/UnitConverterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/UnitConverterTest.php
new file mode 100644
index 00000000..699be6cc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Number/UnitConverterTest.php
@@ -0,0 +1,271 @@
+<?php
+
+namespace SMW\Tests\DataValues\Number;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\Number\UnitConverter;
+use SMW\Tests\TestEnvironment;
+use SMWNumberValue as NumberValue;
+
+/**
+ * @covers \SMW\DataValues\Number\UnitConverter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class UnitConverterTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $numberValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ UnitConverter::class,
+ new UnitConverter( $numberValue )
+ );
+ }
+
+ public function testErrorOnMissingConversionData() {
+
+ $numberValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new UnitConverter(
+ $numberValue
+ );
+
+ $instance->fetchConversionData(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ /**
+ * @dataProvider conversionDataProvider
+ */
+ public function testFetchConversionData( $thousands, $decimal, $correspondsTo, $unitIds, $unitFactors, $mainUnit, $prefixalUnitPreference ) {
+
+ $cachedPropertyValuesPrefetcher = $this->getMockBuilder( '\SMW\CachedPropertyValuesPrefetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [
+ $this->dataItemFactory->newDIBlob( $correspondsTo )
+ ] ) );
+
+ $numberValue = new NumberValue();
+
+ $numberValue->setOption(
+ NumberValue::THOUSANDS_SEPARATOR,
+ $thousands
+ );
+
+ $numberValue->setOption(
+ NumberValue::DECIMAL_SEPARATOR,
+ $decimal
+ );
+
+ $instance = new UnitConverter(
+ $numberValue,
+ $cachedPropertyValuesPrefetcher
+ );
+
+ $instance->fetchConversionData(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+
+ $this->assertEquals(
+ $unitIds,
+ $instance->getUnitIds()
+ );
+
+ $this->assertEquals(
+ $unitFactors,
+ $instance->getUnitFactors()
+ );
+
+ $this->assertEquals(
+ $mainUnit,
+ $instance->getMainUnit()
+ );
+
+ $this->assertEquals(
+ $prefixalUnitPreference,
+ $instance->getPrefixalUnitPreference()
+ );
+ }
+
+ public function testInitConversionData() {
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->any() )
+ ->method( 'has' )
+ ->will( $this->onConsecutiveCalls( false, true ) );
+
+ $blobStore = $this->getMockBuilder( '\Onoi\BlobStore\BlobStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $blobStore->expects( $this->exactly( 2 ) )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $blobStore->expects( $this->once() )
+ ->method( 'save' );
+
+ $cachedPropertyValuesPrefetcher = $this->getMockBuilder( '\SMW\CachedPropertyValuesPrefetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cachedPropertyValuesPrefetcher->expects( $this->atLeastOnce() )
+ ->method( 'getBlobStore' )
+ ->will( $this->returnValue( $blobStore ) );
+
+ $cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [
+ $this->dataItemFactory->newDIBlob( 'Foo' )
+ ] ) );
+
+ $numberValue = new NumberValue();
+
+ $instance = new UnitConverter(
+ $numberValue,
+ $cachedPropertyValuesPrefetcher
+ );
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance->initConversionData( $property );
+
+ // Cached
+ $instance->initConversionData( $property);
+ }
+
+ public function conversionDataProvider() {
+
+ $provider[] = [
+ ',',
+ '.',
+ 'Â¥,JPY,Japanese Yen 1.5',
+ [
+ 'Â¥' => 'Â¥',
+ 'JPY' => 'Â¥',
+ 'JapaneseYen' => 'Â¥',
+ '' => ''
+ ],
+ [
+ '' => 1,
+ 'Â¥' => 1.5
+ ],
+ '',
+ [
+ 'Â¥' => true,
+ 'JPY' => true,
+ 'JapaneseYen' => true
+ ]
+ ];
+
+ $provider[] = [
+ ',',
+ '.',
+ '0.5 British Pound, GBP, pounds sterling, £',
+ [
+ 'BritishPound' => 'BritishPound',
+ 'GBP' => 'BritishPound',
+ 'poundssterling' => 'BritishPound',
+ '£' => 'BritishPound',
+ '' => ''
+ ],
+ [
+ '' => 1,
+ 'BritishPound' => 0.5
+ ],
+ '',
+ [
+ 'BritishPound' => false,
+ 'GBP' => false,
+ 'poundssterling' => false,
+ '£' => false
+ ]
+ ];
+
+ $provider[] = [
+ '.',
+ ',',
+ '0,5 thousand rub., thousand ₽',
+ [
+ 'thousandrub.' => 'thousandrub.',
+ 'thousand₽' => 'thousandrub.',
+ '' => ''
+ ],
+ [
+ 'thousandrub.' => 0.5,
+ '' => 1
+ ],
+ '',
+ [
+ 'thousandrub.' => false,
+ 'thousand₽' => false
+ ]
+ ];
+
+ $provider[] = [
+ '.',
+ ',',
+ '€ 1',
+ [
+ '€' => '€',
+ '' => ''
+ ],
+ [
+ '€' => 1,
+ '' => 1
+ ],
+ '€',
+ [
+ '€' => true,
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyChainValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyChainValueTest.php
new file mode 100644
index 00000000..2f1691f2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyChainValueTest.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\PropertyChainValue;
+use SMW\DIProperty;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\PropertyChainValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyChainValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\PropertyChainValue',
+ new PropertyChainValue()
+ );
+ }
+
+ public function testIsChained() {
+
+ $this->assertFalse(
+ PropertyChainValue::isChained( 'Foo' )
+ );
+
+ $this->assertTrue(
+ PropertyChainValue::isChained( 'Foo.Bar' )
+ );
+ }
+
+ public function testErrorOnUnchainedValue() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testGetLastPropertyChainValue() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo.Bar' );
+
+ $this->assertEquals(
+ new DIProperty( 'Bar' ),
+ $instance->getLastPropertyChainValue()->getDataItem()
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIBlob',
+ $instance->getDataItem()
+ );
+ }
+
+ public function testGetPropertyChainValues() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo.Bar' );
+
+ $this->assertCount(
+ 1,
+ $instance->getPropertyChainValues()
+ );
+ }
+
+ public function testGetWikiValue() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo.Bar' );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->getWikiValue()
+ );
+ }
+
+ public function testGetShortWikiText() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo.Bar' );
+
+ $this->assertEquals(
+ 'Bar&nbsp;<span title="Foo.Bar">â ‰</span>',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertEquals(
+ $this->testEnvironment->replaceNamespaceWithLocalizedText( SMW_NS_PROPERTY, '[[:Property:Bar|Bar]]&nbsp;<span title="Foo.Bar">â ‰</span>' ),
+ $instance->getShortWikiText( 'linker' )
+ );
+ }
+
+ public function testGetLongWikiText() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo.Bar' );
+
+ $this->assertEquals(
+ $this->testEnvironment->replaceNamespaceWithLocalizedText( SMW_NS_PROPERTY, 'Property:Bar&nbsp;<span title="Foo.Bar">â ‰</span>' ),
+ $instance->getLongWikiText()
+ );
+
+ $this->assertEquals(
+ $this->testEnvironment->replaceNamespaceWithLocalizedText( SMW_NS_PROPERTY, '[[:Property:Bar|Bar]]&nbsp;<span title="Foo.Bar">â ‰</span>' ),
+ $instance->getLongWikiText( 'linker' )
+ );
+ }
+
+ public function testGetShortHTMLText() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo.Bar' );
+
+ $this->assertEquals(
+ 'Bar&nbsp;<span title="Foo.Bar">â ‰</span>',
+ $instance->getShortHTMLText()
+ );
+ }
+
+ public function testGetLongHTMLText() {
+
+ $instance = new PropertyChainValue();
+
+ $instance->setUserValue( 'Foo.Bar' );
+
+ $this->assertEquals(
+ $this->testEnvironment->replaceNamespaceWithLocalizedText( SMW_NS_PROPERTY, 'Property:Bar&nbsp;<span title="Foo.Bar">â ‰</span>' ),
+ $instance->getLongHTMLText()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyValueTest.php
new file mode 100644
index 00000000..d2cf6532
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/PropertyValueTest.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\PropertyValue;
+
+/**
+ * @covers \SMW\DataValues\PropertyValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class PropertyValueTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertyValue::class,
+ new PropertyValue()
+ );
+ }
+
+ /**
+ * @dataProvider featuresProvider
+ */
+ public function testOptions( $options, $expected ) {
+
+ $instance = new PropertyValue();
+ $instance->setOption( 'smwgDVFeatures', $options );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getOption( 'smwgDVFeatures' )
+ );
+ }
+
+ public function featuresProvider() {
+
+ $provider[] = [
+ SMW_DV_PROV_REDI,
+ true
+ ];
+
+ $provider[] = [
+ SMW_DV_NONE | SMW_DV_PROV_REDI,
+ true
+ ];
+
+ $provider[] = [
+ SMW_DV_NONE,
+ false
+ ];
+
+ $provider[] = [
+ false,
+ false
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ReferenceValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ReferenceValueTest.php
new file mode 100644
index 00000000..06de9cd3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ReferenceValueTest.php
@@ -0,0 +1,184 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ReferenceValue;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\ReferenceValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ReferenceValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ReferenceValue',
+ new ReferenceValue()
+ );
+ }
+
+ public function testGetPropertyDataItems() {
+
+ $expected = [
+ $this->dataItemFactory->newDIProperty( 'Bar' ),
+ $this->dataItemFactory->newDIProperty( 'Foobar' )
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getFieldListBy' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar;Foobar' ) ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new ReferenceValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getPropertyDataItems()
+ );
+
+ $this->assertEquals(
+ $this->dataItemFactory->newDIProperty( 'Foobar' ),
+ $instance->getPropertyDataItemByIndex( 'Foobar' )
+ );
+ }
+
+ public function testParseValue() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getFieldListBy' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar;Foobar' ) ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new ReferenceValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( '123;abc' );
+ $container = $instance->getDataItem();
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $container
+ );
+
+ $semanticData = $container->getSemanticData();
+
+ $this->assertTrue(
+ $semanticData->hasProperty( $this->dataItemFactory->newDIProperty( 'Foobar' ) )
+ );
+ }
+
+ public function testParseValueOnMissingValues() {
+
+ $instance = new ReferenceValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( '' );
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $instance->getDataItem()
+ );
+ }
+
+ public function testParseValueWithErroredDv() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getFieldListBy' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar;Foobar' ) ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new ReferenceValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( 'Foo;<>Foo' );
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $instance->getDataItem()
+ );
+
+ $this->assertContains(
+ "smw-datavalue-wikipage-property-invalid-title",
+ implode( ' ', $instance->getErrors() )
+ );
+ }
+
+ public function testGetValuesFromStringWithEncodedSemicolon() {
+
+ $instance = new ReferenceValue();
+
+ $this->assertEquals(
+ [ 'abc', '1;2', 3 ],
+ $instance->getValuesFromString( 'abc;1\;2;3' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/StringValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/StringValueTest.php
new file mode 100644
index 00000000..b16a29ca
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/StringValueTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\StringValue;
+use SMW\DataValues\ValueFormatters\StringValueFormatter;
+
+/**
+ * @covers \SMW\DataValues\StringValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class StringValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ StringValue::class,
+ new StringValue( '_txt' )
+ );
+ }
+
+ public function testGetLength() {
+
+ $instance = new StringValue( '_txt' );
+
+ $stringValueFormatter = new StringValueFormatter();
+ $stringValueFormatter->setDataValue( $instance );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $stringValueFormatter ) );
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( 'abcdefã‚ã„ã†ã‚¨ã‚ª' );
+
+ $this->assertEquals(
+ 11,
+ $instance->getLength()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TelephoneUriValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TelephoneUriValueTest.php
new file mode 100644
index 00000000..0a3e75a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TelephoneUriValueTest.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\TelephoneUriValue;
+
+/**
+ * @covers \SMW\DataValues\TelephoneUriValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class TelephoneUriValueTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\TelephoneUriValue',
+ new TelephoneUriValue()
+ );
+
+ $this->assertInstanceOf(
+ '\SMWURIValue',
+ new TelephoneUriValue()
+ );
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TemperatureValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TemperatureValueTest.php
new file mode 100644
index 00000000..8ceb498a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TemperatureValueTest.php
@@ -0,0 +1,207 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\TemperatureValue;
+use SMW\DataValues\ValueFormatters\NumberValueFormatter;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\TemperatureValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class TemperatureValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getPropertySpecificationLookup' )
+ ->will( $this->returnValue( $this->propertySpecificationLookup ) );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\TemperatureValue',
+ new TemperatureValue()
+ );
+ }
+
+ public function testSetUserValueToReturnKelvinForAnyNonPreferredDisplayUnit() {
+
+ $instance = new TemperatureValue();
+
+ $numberValueFormatter = new NumberValueFormatter();
+ $numberValueFormatter->setDataValue( $instance );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $numberValueFormatter ) );
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( '100 °C' );
+
+ $this->assertContains(
+ '373.15 K',
+ $instance->getWikiValue()
+ );
+
+ $instance->setUserValue( '100 Fahrenheit' );
+
+ $this->assertContains(
+ '310.92777777778 K',
+ $instance->getWikiValue()
+ );
+
+ $this->assertContains(
+ '100 Fahrenheit',
+ $instance->getShortWikiText()
+ );
+ }
+
+ public function testSetUserValueOnUnknownUnit() {
+
+ $instance = new TemperatureValue();
+
+ $numberValueFormatter = new NumberValueFormatter();
+ $numberValueFormatter->setDataValue( $instance );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $numberValueFormatter ) );
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setUserValue( '100 Unknown' );
+
+ $this->assertContains(
+ 'error',
+ $instance->getWikiValue()
+ );
+ }
+
+ public function testSetUserValueToReturnOnPreferredDisplayUnit() {
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'getDisplayUnits' )
+ ->will( $this->returnValue( [ 'Celsius' ] ) );
+
+ $instance = new TemperatureValue();
+
+ $numberValueFormatter = new NumberValueFormatter();
+ $numberValueFormatter->setDataValue( $instance );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $numberValueFormatter ) );
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( '100 °C' );
+
+ $this->assertContains(
+ '373.15 K',
+ $instance->getWikiValue()
+ );
+
+ $this->assertContains(
+ '100 °C',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertContains(
+ '100&#160;°C (373&#160;K, 212&#160;°F, 672&#160;°R)',
+ $instance->getLongWikiText()
+ );
+ }
+
+ public function testSetUserValueToReturnOnPreferredDisplayPrecision() {
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'getDisplayPrecision' )
+ ->will( $this->returnValue( 0 ) );
+
+ $instance = new TemperatureValue();
+
+ $numberValueFormatter = new NumberValueFormatter();
+ $numberValueFormatter->setDataValue( $instance );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $numberValueFormatter ) );
+
+ $instance->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( '100 °C' );
+
+ $this->assertContains(
+ '373 K',
+ $instance->getWikiValue()
+ );
+
+ $this->assertContains(
+ '100 °C',
+ $instance->getShortWikiText()
+ );
+
+ $this->assertContains(
+ '373&#160;K (100&#160;°C, 212&#160;°F, 672&#160;°R)',
+ $instance->getLongWikiText()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/ComponentsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/ComponentsTest.php
new file mode 100644
index 00000000..e1c4a953
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/ComponentsTest.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace SMW\Tests\DataValues\Time;
+
+use SMW\DataValues\Time\Components;
+
+/**
+ * @covers \SMW\DataValues\Time\Components
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ComponentsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testPublicProperties() {
+
+ $this->assertInternalType(
+ 'array',
+ Components::$months
+ );
+
+ $this->assertInternalType(
+ 'array',
+ Components::$monthsShort
+ );
+ }
+
+ public function testGet() {
+
+ $instance = new Components( [ 'foo' => 'bar' ] );
+
+ $this->assertEquals(
+ false,
+ $instance->get( 'bar' )
+ );
+
+ $this->assertEquals(
+ 'bar',
+ $instance->get( 'foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/IntlTimeFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/IntlTimeFormatterTest.php
new file mode 100644
index 00000000..d21d11ff
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/IntlTimeFormatterTest.php
@@ -0,0 +1,272 @@
+<?php
+
+namespace SMW\Tests\DataValues\Time;
+
+use SMW\DataValues\Time\IntlTimeFormatter;
+use SMW\Localizer;
+use SMWDITime as DITime;
+
+/**
+ * @covers \SMW\DataValues\Time\IntlTimeFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class IntlTimeFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $dataItem = $this->getMockBuilder( '\SMWDITime' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ IntlTimeFormatter::class,
+ new IntlTimeFormatter( $dataItem )
+ );
+ }
+
+ /**
+ * @dataProvider formatProvider
+ */
+ public function testFormat( $serialization, $languageCode, $formatOption, $expected ) {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new IntlTimeFormatter(
+ DITime::doUnserialize( $serialization ),
+ Localizer::getInstance()->getLanguage( $languageCode )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $formatOption )
+ );
+ }
+
+ /**
+ * @dataProvider localizedFormatProvider
+ */
+ public function testGetLocalizedFormat( $serialization, $languageCode, $flag, $expected ) {
+
+ $instance = new IntlTimeFormatter(
+ DITime::doUnserialize( $serialization ),
+ Localizer::getInstance()->getLanguage( $languageCode )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getLocalizedFormat( $flag )
+ );
+ }
+
+ public function testContainsValidDateFormatRule() {
+
+ $formatOption = 'F Y/m/d H:i:s';
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new IntlTimeFormatter(
+ DITime::doUnserialize( '1/2000/12/12/1/1/20.200' ),
+ $language
+ );
+
+ $this->assertTrue(
+ $instance->containsValidDateFormatRule( $formatOption )
+ );
+ }
+
+ public function testFormatWithLocalizedMonthReplacement() {
+
+ // F - A full textual representation of a month, such as January or March
+ $formatOption = 'F Y/m/d H:i:s';
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->once() )
+ ->method( 'getMonthName' )
+ ->with( $this->equalTo( '12' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new IntlTimeFormatter(
+ DITime::doUnserialize( '1/2000/12/12/1/1/20.200' ),
+ $language
+ );
+
+ $this->assertEquals(
+ 'Foo 2000/12/12 01:01:20',
+ $instance->format( $formatOption )
+ );
+ }
+
+ public function formatProvider() {
+
+ #0
+ $provider[] = [
+ '1/2000/12/12/1/1/20/200',
+ 'en',
+ 'Y/m/d H:i:s',
+ '2000/12/12 01:01:20'
+ ];
+
+ #1
+ $provider[] = [
+ '2/2000/12/12/1/1/20/200',
+ 'en',
+ 'Y/m/d H:i:s',
+ '2000/12/12 01:01:20'
+ ];
+
+ #2
+ $provider[] = [
+ '1/2000/12/12/1/1/20.200',
+ 'en',
+ 'Y/m/d H:i:s.u',
+ '2000/12/12 01:01:20.200000'
+ ];
+
+ // Skip on HHVM to avoid .888500 vs. .888499 msec @see hhvm#6899
+ // https://bugs.php.net/bug.php?id=76822
+ if ( !defined( 'HHVM_VERSION' ) && version_compare( PHP_VERSION, '7.2', '<' ) ) {
+ #3
+ $provider[] = [
+ '2/1300/11/02/12/03/25.888499949',
+ 'en',
+ 'Y-m-d H:i:s.u',
+ '1300-11-02 12:03:25.888500'
+ ];
+
+ #4 time alone doesn't require a calendar model
+ $provider[] = [
+ '2/1300/11/02/12/03/25.888499949',
+ 'en',
+ 'H:i:s.u',
+ '12:03:25.888500'
+ ];
+ }
+
+ #5
+ $provider['on monthnumber 12'] = [
+ '1/2000/12/12',
+ 'en',
+ 'Y-m-d M',
+ '2000-12-12 Dec'
+ ];
+
+ #6
+ $provider['on daynumber 7'] = [
+ '1/2016/05/08/1/1/20/200',
+ 'en',
+ 'Y-m-d D',
+ '2016-05-08 Sun'
+ ];
+
+ #7
+ $provider['on timezone 1'] = [
+ '1/1970/1/12/11/43/0/14',
+ 'en',
+ 'Y-m-d H:i:s T',
+ '1970-01-12 11:43:00 UTC'
+ ];
+
+ return $provider;
+ }
+
+ public function localizedFormatProvider() {
+
+ #0
+ $provider[] = [
+ '1/2000/12/12/1/1/20/200',
+ 'en',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '01:01:20, 12 December 2000'
+ ];
+
+ #1
+ $provider[] = [
+ '1/2000/12/12/1/1/20/200',
+ 'ja',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '2000å¹´12月12æ—¥ (ç«) 01:01:20'
+ ];
+
+ #2
+ $provider[] = [
+ '1/2000/12/12/1/1/20/200',
+ 'es',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '01:01:20 12 dic 2000'
+ ];
+
+ #3
+ $provider['on daynumber 1'] = [
+ '1/2016/05/02/1/1/20/200',
+ 'ja',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '2016年5月2日 (月) 01:01:20'
+ ];
+
+ #4
+ $provider['on daynumber 7'] = [
+ '1/2016/05/08/1/1/20/200',
+ 'ja',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '2016年5月8日 (日) 01:01:20'
+ ];
+
+ #5
+ $provider['midnight-ja'] = [
+ '1/2016/05/08/00/00/00/00',
+ 'ja',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '2016年5月8日 (日) 00:00:00'
+ ];
+
+ #6
+ $provider['midnight-en'] = [
+ '1/2016/05/08/0/0/0/0',
+ 'en',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '00:00:00, 8 May 2016'
+ ];
+
+ #7
+ $provider['after-midnight'] = [
+ '1/2016/05/08/0/0/01/0',
+ 'en',
+ IntlTimeFormatter::LOCL_DEFAULT,
+ '00:00:01, 8 May 2016'
+ ];
+
+ #8
+ $provider['timezone-short'] = [
+ '1/1970/1/12/11/43/0/14',
+ 'en',
+ IntlTimeFormatter::LOCL_TIMEZONE,
+ '12:43:00 BST, 12 January 1970'
+ ];
+
+ #9
+ // -'07:43:00 America/Cuiaba, 12 January 1970'
+ // +'08:43:00 America/Cuiaba, 12 January 1970'
+ // Because of Daylight Saving Time UTC-3/Standard Time UTC-4
+ // $provider['timezone-long'] = array(
+ // '1/1970/1/12/11/43/0/America/Cuiaba',
+ // 'en',
+ // IntlTimeFormatter::LOCL_TIMEZONE,
+ // '07:43:00 America/Cuiaba, 12 January 1970'
+ // );
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/JulianDayTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/JulianDayTest.php
new file mode 100644
index 00000000..1a722329
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/JulianDayTest.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace SMW\Tests\DataValues\Time;
+
+use SMW\DataValues\Time\JulianDay;
+
+/**
+ * @covers \SMW\DataValues\Time\JulianDay
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class JulianDayTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testConvert( $calendarModel, $seralization, $jdValue ) {
+
+ list( $year, $month, $day, $hour, $minute, $second ) = explode( '/', $seralization );
+
+ $this->assertEquals(
+ $jdValue,
+ JulianDay::getJD( $calendarModel, $year, $month, $day, $hour, $minute, $second )
+ );
+ }
+
+ public function testGetJD_Issue2454() {
+
+ $offset = -4 / 24;
+
+ $this->assertSame(
+ 2457869.3333333,
+ JulianDay::getJD( 1, 2017, 4, 25, 20, 0, 0 )
+ );
+
+ $this->assertNotSame(
+ 2457869.5,
+ JulianDay::getJD( 1, 2017, 4, 25, 20, 0, 0 ) - $offset // returns 2457869.4999999665
+ );
+
+ $this->assertSame(
+ 2457869.5,
+ JulianDay::format( JulianDay::getJD( 1, 2017, 4, 25, 20, 0, 0 ) - $offset )
+ );
+ }
+
+ public function valueProvider() {
+
+ $provider[] = [
+ JulianDay::CM_JULIAN,
+ '1352/01/01/0/0/0',
+ '2214875.500000'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_GREGORIAN,
+ '2100/10/04/0/0/0',
+ '2488345.500000'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_GREGORIAN,
+ '2100/10/04/0/0/0',
+ '2488345.500000'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_JULIAN,
+ '1582/10/04/0/0/0',
+ '2299159.500000'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_GREGORIAN,
+ '1582/10/15/0/0/0',
+ '2299160.5'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_JULIAN,
+ '-900/10/4/0/0/0',
+ '1392974.500000'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_JULIAN,
+ '-4713/01/02/0/0/0',
+ '0.5'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_JULIAN,
+ '-4713/01/02/12/0/0/0',
+ '1'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_JULIAN,
+ '-9000/10/4/0/0/0',
+ '-1565550.5'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_GREGORIAN,
+ '2100/10/4/13/55/55',
+ '2488346.0804977'
+ ];
+
+ $provider[] = [
+ JulianDay::CM_GREGORIAN,
+ '2100/10/4/13/55/55',
+ 2488346.0804977
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/TimezoneTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/TimezoneTest.php
new file mode 100644
index 00000000..68396821
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/Time/TimezoneTest.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace SMW\Tests\DataValues\Time;
+
+use DateTime;
+use SMW\DataValues\Time\Timezone;
+
+/**
+ * @covers \SMW\DataValues\Time\Timezone
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TimezoneTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Timezone::class,
+ new Timezone()
+ );
+ }
+
+ public function testListShortAbbreviations() {
+
+ $this->assertInternalType(
+ 'array',
+ Timezone::listShortAbbreviations()
+ );
+ }
+
+ /**
+ * @dataProvider timezoneProvider
+ */
+ public function testIsValidAndIsMilitary( $abbrevation, $isValid, $isMilitary ) {
+
+ $this->assertEquals(
+ $isValid,
+ Timezone::isValid( $abbrevation )
+ );
+
+ $this->assertEquals(
+ $isMilitary,
+ Timezone::isMilitary( $abbrevation )
+ );
+ }
+
+ /**
+ * @dataProvider timezoneProvider
+ */
+ public function testGetIdByAbbreviation( $abbrevation, $isValid, $isMilitary, $expectedId ) {
+
+ $this->assertEquals(
+ $expectedId,
+ Timezone::getIdByAbbreviation( $abbrevation )
+ );
+ }
+
+ /**
+ * @dataProvider offsetProvider
+ */
+ public function testGetOffsetByAbbreviation( $abbrevation, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ Timezone::getOffsetByAbbreviation( $abbrevation )
+ );
+ }
+
+ public function testGetModifiedTime() {
+
+ $dti = new DateTime( '2017-08-01 10:00:00+00:00' );
+ $tz = 'Asia/Tokyo';
+
+ $dateTime = Timezone::getModifiedTime( $dti, $tz );
+
+ $this->assertEquals(
+ '2017-08-01 19:00:00',
+ $dateTime->format( 'Y-m-d H:i:s' )
+ );
+ }
+
+ public function timezoneProvider() {
+
+ $provider[] = [
+ 'UTC',
+ true,
+ false,
+ 0
+ ];
+
+ $provider[] = [
+ 'Z',
+ true,
+ true,
+ 1
+ ];
+
+ $provider[] = [
+ 'Unknown',
+ false,
+ false,
+ false
+ ];
+
+ $provider[] = [
+ 'Asia/Tokyo',
+ true,
+ false,
+ 'Asia/Tokyo'
+ ];
+
+ $provider[] = [
+ 'America/Los Angeles',
+ true,
+ false,
+ 'America/Los_Angeles'
+ ];
+
+ $provider[] = [
+ 'America/Los_Angeles',
+ true,
+ false,
+ 'America/Los_Angeles'
+ ];
+
+ return $provider;
+ }
+
+ public function offsetProvider() {
+
+ $provider[] = [
+ 'UTC',
+ 0
+ ];
+
+ $provider[] = [
+ 'Z',
+ 0
+ ];
+
+ $provider[] = [
+ 'Unknown',
+ false
+ ];
+
+ $provider[] = [
+ 'Asia/Tokyo',
+ 32400
+ ];
+
+ // Maybe return PST or PDT during Daylight Savings Time
+ /*
+ $provider[] = array(
+ 'America/Los Angeles',
+ -25200
+ );
+
+ $provider[] = array(
+ 'America/Los_Angeles',
+ -25200
+ );
+ */
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TypesValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TypesValueTest.php
new file mode 100644
index 00000000..aa593f8b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/TypesValueTest.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataValues\TypesValue;
+use SMW\DataValues\ValueParsers\TypesValueParser;
+
+/**
+ * @covers \SMW\DataValues\TypesValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TypesValueTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TypesValue::class,
+ new TypesValue()
+ );
+
+ // FIXME Legacy naming remove in 3.1.x
+ $this->assertInstanceOf(
+ '\SMWTypesValue',
+ new TypesValue()
+ );
+ }
+
+ public function testNewFromTypeId() {
+
+ $this->assertInstanceOf(
+ TypesValue::class,
+ TypesValue::newFromTypeId( '_dat' )
+ );
+ }
+
+ /**
+ * @dataProvider typeLabelProvider
+ */
+ public function testNewFromTypeId_GetWikiValue( $type, $label ) {
+
+ $this->assertEquals(
+ $label,
+ TypesValue::newFromTypeId( $type )->getWikiValue()
+ );
+ }
+
+ /**
+ * @dataProvider typeUriProvider
+ */
+ public function testGetTypeUriFromTypeId( $type, $url ) {
+
+ $this->assertEquals(
+ $url,
+ TypesValue::getTypeUriFromTypeId( $type )->getUri()
+ );
+ }
+
+ /**
+ * @dataProvider userWikiValueProvider
+ */
+ public function testSetUserValue_GetWikiValue( $value, $expected ) {
+
+ $instance = new TypesValue();
+ $instance->setUserValue( $value );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getWikiValue()
+ );
+ }
+
+ public function typeLabelProvider() {
+
+ yield [
+ '_dat',
+ 'Date'
+ ];
+
+ yield [
+ '_boo',
+ 'Boolean'
+ ];
+
+ yield [
+ 'foo',
+ ''
+ ];
+ }
+
+ public function typeUriProvider() {
+
+ yield [
+ '_dat',
+ 'http://semantic-mediawiki.org/swivt/1.0#_dat'
+ ];
+
+ yield [
+ '_boo',
+ 'http://semantic-mediawiki.org/swivt/1.0#_boo'
+ ];
+
+ yield [
+ 'foo',
+ 'http://semantic-mediawiki.org/swivt/1.0#foo'
+ ];
+ }
+
+ public function userWikiValueProvider() {
+
+ yield [
+ '_dat',
+ 'Date'
+ ];
+
+ yield [
+ 'Date',
+ 'Date'
+ ];
+
+ yield [
+ 'Foo',
+ 'Foo'
+ ];
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/UniquenessConstraintValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/UniquenessConstraintValueTest.php
new file mode 100644
index 00000000..7040ee03
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/UniquenessConstraintValueTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\UniquenessConstraintValue;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\UniquenessConstraintValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class UniquenessConstraintValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\UniquenessConstraintValue',
+ new UniquenessConstraintValue()
+ );
+ }
+
+ public function testErrorForMissingFeatureSetting() {
+
+ $instance = new UniquenessConstraintValue();
+
+ $instance->setOption( 'smwgDVFeatures', '' );
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testErrorForInvalidBoolean() {
+
+ $instance = new UniquenessConstraintValue();
+
+ $instance->setOption( 'smwgDVFeatures', SMW_DV_PVUC );
+ $instance->setUserValue( 'Foo' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/CodeStringValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/CodeStringValueFormatterTest.php
new file mode 100644
index 00000000..b3221f9c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/CodeStringValueFormatterTest.php
@@ -0,0 +1,153 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataValueFactory;
+use SMW\DataValues\ValueFormatters\CodeStringValueFormatter;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\CodeStringValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class CodeStringValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CodeStringValueFormatter::class,
+ new CodeStringValueFormatter()
+ );
+ }
+
+ /**
+ * @dataProvider stringValueProvider
+ */
+ public function testFormat( $userValue, $type, $linker, $expected ) {
+
+ $codeStringValue = DataValueFactory::getInstance()->newDataValueByType( '_cod' );
+ $codeStringValue->setUserValue( $userValue );
+
+ $instance = new CodeStringValueFormatter();
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $codeStringValue, [ $type, $linker ] )
+ );
+ }
+
+ public function stringValueProvider() {
+
+ $provider[] = [
+ 'foo',
+ CodeStringValueFormatter::VALUE,
+ null,
+ 'foo'
+ ];
+
+ $provider[] = [
+ 'foo',
+ CodeStringValueFormatter::WIKI_SHORT,
+ null,
+ '<div class="smwpre">foo</div>'
+ ];
+
+ $provider[] = [
+ 'foo',
+ CodeStringValueFormatter::HTML_SHORT,
+ null,
+ '<div class="smwpre">foo</div>'
+ ];
+
+ $provider[] = [
+ 'foo',
+ CodeStringValueFormatter::WIKI_LONG,
+ null,
+ '<div class="smwpre"><div style="min-height:5em; overflow:auto;">foo</div></div>'
+ ];
+
+ $provider[] = [
+ 'foo',
+ CodeStringValueFormatter::HTML_LONG,
+ null,
+ '<div class="smwpre"><div style="min-height:5em; overflow:auto;">foo</div></div>'
+ ];
+
+ $provider[] = [
+ '<code><nowiki>&#x005B;&#x005B;Foo]]</nowiki></code>',
+ CodeStringValueFormatter::HTML_LONG,
+ null,
+ '<div class="smwpre"><div style="min-height:5em; overflow:auto;">&#91;&#91;Foo]]</div></div>'
+ ];
+
+ $provider[] = [
+ '<code><nowiki>[[Foo]]</nowiki></code>',
+ CodeStringValueFormatter::HTML_LONG,
+ null,
+ '<div class="smwpre"><div style="min-height:5em; overflow:auto;">&#91;&#91;Foo]]</div></div>'
+ ];
+
+ // > 255
+ $text = 'Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede ' .
+ 'lorem nulla justo diam wisi. Libero Nam turpis neque leo scelerisque nec habitasse a lacus mattis. Accumsan ' .
+ 'tincidunt Sed adipiscing nec facilisis tortor Nunc Sed ipsum tellus';
+
+ $expected = '<div class="smwpre"><div style="min-height:5em; overflow:auto;">Lorem&#160;ipsum&#160;dolor&#160;sit&#160;amet&#160;' .
+ 'consectetuer&#160;justo&#160;Nam&#160;quis&#160;lobortis&#160;vel.&#160;Sapien&#160;nulla&#160;enim&#160;Lorem&#160;enim&#160;' .
+ 'pede&#160;lorem&#160;nulla&#160;justo&#160;diam&#160;wisi.&#160;Libero&#160;Nam&#160;turpis&#160;neque&#160;leo&#160;' .
+ 'scelerisque&#160;nec&#160;habitasse&#160;a&#160;lacus&#160;mattis.&#160;Accumsan&#160;tincidunt&#160;Sed&#160;adipiscing&#160;' .
+ 'nec&#160;facilisis&#160;tortor&#160;Nunc&#160;Sed&#160;ipsum&#160;tellus</div></div>';
+
+ $provider[] = [
+ $text,
+ CodeStringValueFormatter::HTML_LONG,
+ null,
+ $expected
+ ];
+
+ $provider[] = [
+ $text,
+ CodeStringValueFormatter::WIKI_LONG,
+ null,
+ $expected
+ ];
+
+ // XMLContentEncode
+ $provider[] = [
+ '<foo>',
+ CodeStringValueFormatter::HTML_LONG,
+ null,
+ '<div class="smwpre"><div style="min-height:5em; overflow:auto;">&lt;foo&gt;</div></div>'
+ ];
+
+ $provider[] = [
+ '<foo>',
+ CodeStringValueFormatter::HTML_SHORT,
+ null,
+ '<div class="smwpre">&lt;foo&gt;</div>'
+ ];
+
+ $provider[] = [
+ '*Foo',
+ CodeStringValueFormatter::WIKI_LONG,
+ null,
+ '<div class="smwpre"><div style="min-height:5em; overflow:auto;">*Foo</div></div>'
+ ];
+
+ // JSON
+ $jsonString = '{"limit": 50,"offset": 0,"sort": [],"order": [],"mode": 1}';
+ $provider[] = [
+ $jsonString,
+ CodeStringValueFormatter::WIKI_LONG,
+ null,
+ '<div class="smwpre"><div style="min-height:5em; overflow:auto;">' . CodeStringValueFormatter::asJson( $jsonString ) . '</div></div>'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/DispatchingDataValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/DispatchingDataValueFormatterTest.php
new file mode 100644
index 00000000..77ecf082
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/DispatchingDataValueFormatterTest.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataValues\ValueFormatters\DispatchingDataValueFormatter;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\DispatchingDataValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DispatchingDataValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\DispatchingDataValueFormatter',
+ new DispatchingDataValueFormatter()
+ );
+ }
+
+ public function testGetDataValueFormatterForMatchableDataValue() {
+
+ $dataValueFormatter = $this->getMockBuilder( '\SMW\DataValues\ValueFormatters\DataValueFormatter' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataValueFormatter->expects( $this->once() )
+ ->method( 'isFormatterFor' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DispatchingDataValueFormatter();
+ $instance->addDataValueFormatter( $dataValueFormatter );
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\DataValueFormatter',
+ $instance->getDataValueFormatterFor( $dataValue )
+ );
+ }
+
+ public function testGetDefaultDispatchingDataValueFormatterForMatchableDataValue() {
+
+ $dataValueFormatter = $this->getMockBuilder( '\SMW\DataValues\ValueFormatters\DataValueFormatter' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataValueFormatter->expects( $this->once() )
+ ->method( 'isFormatterFor' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DispatchingDataValueFormatter();
+ $instance->addDefaultDataValueFormatter( $dataValueFormatter );
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\DataValueFormatter',
+ $instance->getDataValueFormatterFor( $dataValue )
+ );
+ }
+
+ public function testPrioritizeDispatchableDataValueFormatter() {
+
+ $dataValueFormatter = $this->getMockBuilder( '\SMW\DataValues\ValueFormatters\DataValueFormatter' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataValueFormatter->expects( $this->once() )
+ ->method( 'isFormatterFor' )
+ ->will( $this->returnValue( true ) );
+
+ $defaultDataValueFormatter = $this->getMockBuilder( '\SMW\DataValues\ValueFormatters\DataValueFormatter' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $defaultDataValueFormatter->expects( $this->never() )
+ ->method( 'isFormatterFor' );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DispatchingDataValueFormatter();
+ $instance->addDefaultDataValueFormatter( $defaultDataValueFormatter );
+ $instance->addDataValueFormatter( $dataValueFormatter );
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\DataValueFormatter',
+ $instance->getDataValueFormatterFor( $dataValue )
+ );
+ }
+
+ public function testTryToGetDataValueFormatterForNonDispatchableDataValueThrowsException() {
+
+ $dataValueFormatter = $this->getMockBuilder( '\SMW\DataValues\ValueFormatters\DataValueFormatter' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataValueFormatter->expects( $this->once() )
+ ->method( 'isFormatterFor' )
+ ->will( $this->returnValue( false ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DispatchingDataValueFormatter();
+ $instance->addDataValueFormatter( $dataValueFormatter );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getDataValueFormatterFor( $dataValue );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/MonolingualTextValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/MonolingualTextValueFormatterTest.php
new file mode 100644
index 00000000..9bdbd8d4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/MonolingualTextValueFormatterTest.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataValues\MonolingualTextValue;
+use SMW\DataValues\ValueFormatters\MonolingualTextValueFormatter;
+use SMW\DataValues\ValueParsers\MonolingualTextValueParser;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\MonolingualTextValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class MonolingualTextValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( new MonolingualTextValueParser() ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\MonolingualTextValueFormatter',
+ new MonolingualTextValueFormatter()
+ );
+ }
+
+ public function testIsFormatterForValidation() {
+
+ $monolingualTextValue = $this->getMockBuilder( '\SMW\DataValues\MonolingualTextValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new MonolingualTextValueFormatter();
+
+ $this->assertTrue(
+ $instance->isFormatterFor( $monolingualTextValue )
+ );
+ }
+
+ public function testToUseCaptionOutput() {
+
+ $monolingualTextValue = new MonolingualTextValue();
+
+ $monolingualTextValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $monolingualTextValue->setCaption( 'ABC' );
+
+ $instance = new MonolingualTextValueFormatter( $monolingualTextValue );
+
+ $this->assertEquals(
+ 'ABC',
+ $instance->format( MonolingualTextValueFormatter::WIKI_SHORT )
+ );
+
+ $this->assertEquals(
+ 'ABC',
+ $instance->format( MonolingualTextValueFormatter::HTML_SHORT )
+ );
+ }
+
+ /**
+ * @dataProvider stringValueProvider
+ */
+ public function testFormat( $stringValue, $type, $linker, $expected ) {
+
+ $monolingualTextValue = new MonolingualTextValue();
+
+ $monolingualTextValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $monolingualTextValue->setUserValue( $stringValue );
+
+ $instance = new MonolingualTextValueFormatter( $monolingualTextValue );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $type, $linker )
+ );
+ }
+
+ public function testTryToFormatOnMissingDataValueThrowsException() {
+
+ $instance = new MonolingualTextValueFormatter();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->format( MonolingualTextValueFormatter::VALUE );
+ }
+
+ public function stringValueProvider() {
+
+ $provider[] = [
+ 'foo@en',
+ MonolingualTextValueFormatter::VALUE,
+ null,
+ 'foo@en'
+ ];
+
+ $provider[] = [
+ 'foo@en',
+ MonolingualTextValueFormatter::WIKI_SHORT,
+ null,
+ 'foo (en)'
+ ];
+
+ $provider[] = [
+ 'foo@en',
+ MonolingualTextValueFormatter::HTML_SHORT,
+ null,
+ 'foo (en)'
+ ];
+
+ $provider[] = [
+ 'foo@en',
+ MonolingualTextValueFormatter::WIKI_LONG,
+ null,
+ 'foo (en)'
+ ];
+
+ $provider[] = [
+ 'foo@en',
+ MonolingualTextValueFormatter::HTML_LONG,
+ null,
+ 'foo (en)'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NoValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NoValueFormatterTest.php
new file mode 100644
index 00000000..51ff75f5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NoValueFormatterTest.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataValues\ValueFormatters\NoValueFormatter;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\NoValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class NoValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\NoValueFormatter',
+ new NoValueFormatter()
+ );
+ }
+
+ public function testIsFormatterForValidation() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new NoValueFormatter();
+
+ $this->assertTrue(
+ $instance->isFormatterFor( $dataValue )
+ );
+ }
+
+ public function testFormat() {
+
+ $dataItem = $this->getMockBuilder( '\SMWDataItem' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSerialization' ] )
+ ->getMockForAbstractClass();
+
+ $dataItem->expects( $this->once() )
+ ->method( 'getSerialization' )
+ ->will( $this->returnValue( 'isFromSerializationMethod' ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid', 'getDataItem' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue->expects( $this->once() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItem ) );
+
+ $instance = new NoValueFormatter( $dataValue );
+
+ $this->assertEquals(
+ 'isFromSerializationMethod',
+ $instance->format( NoValueFormatter::VALUE )
+ );
+ }
+
+ public function testTryToFormatOnMissingDataValueThrowsException() {
+
+ $instance = new NoValueFormatter();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->format( NoValueFormatter::VALUE );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NumberValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NumberValueFormatterTest.php
new file mode 100644
index 00000000..280b80d3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/NumberValueFormatterTest.php
@@ -0,0 +1,215 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataValues\TemperatureValue;
+use SMW\DataValues\ValueFormatters\NumberValueFormatter;
+use SMWNumberValue as NumberValue;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\NumberValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class NumberValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\NumberValueFormatter',
+ new NumberValueFormatter()
+ );
+ }
+
+ public function testIsFormatterForValidation() {
+
+ $numberValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new NumberValueFormatter();
+
+ $this->assertTrue(
+ $instance->isFormatterFor( $numberValue )
+ );
+ }
+
+ /**
+ * @dataProvider numberValueProvider
+ */
+ public function testNumberFormat( $numberUserValue, $type, $linker, $expected ) {
+
+ $numberValue = new NumberValue( '_num' );
+ $numberValue->setUserValue( $numberUserValue );
+
+ $numberValue->setOption( 'user.language', 'en' );
+ $numberValue->setOption( 'content.language', 'en' );
+
+ $instance = new NumberValueFormatter( $numberValue );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $type, $linker )
+ );
+ }
+
+ /**
+ * @dataProvider temperaturValueProvider
+ */
+ public function testTemperaturFormat( $numberUserValue, $type, $linker, $expected ) {
+
+ $temperatureValue = new TemperatureValue( '_num' );
+ $temperatureValue->setUserValue( $numberUserValue );
+
+ $temperatureValue->setOption( 'user.language', 'en' );
+ $temperatureValue->setOption( 'content.language', 'en' );
+
+ $instance = new NumberValueFormatter( $temperatureValue );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $type, $linker )
+ );
+ }
+
+ public function testTryToFormatOnMissingDataValueThrowsException() {
+
+ $instance = new NumberValueFormatter();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->format( NumberValueFormatter::VALUE );
+ }
+
+ public function testTryToFormatWithUnknownType() {
+
+ $numberValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new NumberValueFormatter( $numberValue );
+
+ $this->assertEquals(
+ 'UNKNOWN',
+ $instance->format( 'Foo' )
+ );
+ }
+
+ public function numberValueProvider() {
+
+ $provider['v.1'] = [
+ 'foo',
+ NumberValueFormatter::VALUE,
+ null,
+ 'error'
+ ];
+
+ $provider['v.2'] = [
+ 100,
+ NumberValueFormatter::VALUE,
+ null,
+ 100
+ ];
+
+ $provider['v.3'] = [
+ 0.222,
+ NumberValueFormatter::VALUE,
+ null,
+ 0.222
+ ];
+
+ $provider['ws.1'] = [
+ 100,
+ NumberValueFormatter::WIKI_SHORT,
+ null,
+ 100
+ ];
+
+ $provider['ws.2'] = [
+ 100,
+ NumberValueFormatter::WIKI_SHORT,
+ 'notNull',
+ 100
+ ];
+
+ $provider['hs.1'] = [
+ 100,
+ NumberValueFormatter::HTML_SHORT,
+ null,
+ 100
+ ];
+
+ $provider['wl.1'] = [
+ 100,
+ NumberValueFormatter::WIKI_LONG,
+ null,
+ 100
+ ];
+
+ $provider['wl.2'] = [
+ 100,
+ NumberValueFormatter::WIKI_LONG,
+ 'notNull',
+ 100
+ ];
+
+ $provider['hl.1'] = [
+ 100,
+ NumberValueFormatter::HTML_LONG,
+ null,
+ 100
+ ];
+
+ return $provider;
+ }
+
+ public function temperaturValueProvider() {
+
+ $provider['v.1'] = [
+ '100 K',
+ NumberValueFormatter::VALUE,
+ null,
+ '100 K'
+ ];
+
+ $provider['ws.1'] = [
+ '100 K',
+ NumberValueFormatter::WIKI_SHORT,
+ null,
+ '100 K'
+ ];
+
+ $provider['ws.2'] = [
+ '100 K',
+ NumberValueFormatter::WIKI_SHORT,
+ 'notNull',
+ '<span class="smw-highlighter" data-type="3" data-state="inline" data-title="Unit conversion" title="-173.15 °C -279.67 °F 180 °R ">' .
+ '<span class="smwtext">100 K</span>' .
+ '<span class="smwttcontent">-173.15&#160;°C <br />-279.67&#160;°F <br />180&#160;°R <br /></span></span>'
+ ];
+
+ $provider['wl.1'] = [
+ '100 K',
+ NumberValueFormatter::WIKI_LONG,
+ null,
+ '100&#160;K (-173.15&#160;°C, -279.67&#160;°F, 180&#160;°R)'
+ ];
+
+ $provider['wl.2'] = [
+ '100 K',
+ NumberValueFormatter::WIKI_LONG,
+ 'notNull',
+ '100&#160;K (-173.15&#160;°C, -279.67&#160;°F, 180&#160;°R)'
+ ];
+
+ return $provider;
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/PropertyValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/PropertyValueFormatterTest.php
new file mode 100644
index 00000000..bc374682
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/PropertyValueFormatterTest.php
@@ -0,0 +1,521 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ValueFormatters\PropertyValueFormatter;
+use SMW\DataValues\ValueParsers\PropertyValueParser;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+use SMW\DataValues\PropertyValue;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\PropertyValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $dataItemFactory;
+ private $propertyLabelFinder;
+ private $propertySpecificationLookup;
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertyLabelFinder = $this->getMockBuilder( '\SMW\PropertyLabelFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertyLabelFinder', $this->propertyLabelFinder );
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( new PropertyValueParser() ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\PropertyValueFormatter',
+ new PropertyValueFormatter( $this->propertySpecificationLookup )
+ );
+ }
+
+ public function testIsFormatterForValidation() {
+
+ $propertyValue = $this->getMockBuilder( '\SMWPropertyValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $this->assertTrue(
+ $instance->isFormatterFor( $propertyValue )
+ );
+ }
+
+ public function testFormatWithInvalidFormat() {
+
+ $propertyValue = new PropertyValue();
+ $propertyValue->setDataItem( $this->dataItemFactory->newDIProperty( 'Foo' ) );
+ $propertyValue->setOption( PropertyValue::OPT_NO_HIGHLIGHT, true );
+
+ $propertyValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->format( $propertyValue, [ 'Foo' ] )
+ );
+ }
+
+ public function testFormatWithCaptionOutput() {
+
+ $propertyValue = new PropertyValue();
+ $propertyValue->setDataItem( $this->dataItemFactory->newDIProperty( 'Foo' ) );
+ $propertyValue->setCaption( 'ABC[<>]' );
+ $propertyValue->setOption( PropertyValue::OPT_NO_HIGHLIGHT, true );
+
+ $propertyValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $this->assertEquals(
+ 'ABC[<>]',
+ $instance->format( $propertyValue, [ PropertyValueFormatter::WIKI_SHORT ] )
+ );
+
+ $this->assertEquals(
+ 'ABC[&lt;&gt;]',
+ $instance->format( $propertyValue, [ PropertyValueFormatter::HTML_SHORT ] )
+ );
+ }
+
+
+ public function testFormatWithCaptionOutputAndHighlighter() {
+
+ $propertyValue = new PropertyValue();
+ $propertyValue->setOption( PropertyValue::OPT_NO_HIGHLIGHT, false );
+
+ $propertyValue->setDataItem( $this->dataItemFactory->newDIProperty( 'Foo' ) );
+ $propertyValue->setCaption( 'ABC[<>]' );
+
+ $propertyValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $this->assertContains(
+ '<span class="smwtext">ABC[<>]</span><span class="smwttcontent"></span>',
+ $instance->format( $propertyValue, [ PropertyValueFormatter::WIKI_SHORT ] )
+ );
+
+ $this->assertContains(
+ '<span class="smwtext">ABC[&lt;&gt;]</span><span class="smwttcontent"></span>',
+ $instance->format( $propertyValue, [ PropertyValueFormatter::HTML_SHORT ] )
+ );
+ }
+
+ /**
+ * @dataProvider propertyValueProvider
+ */
+ public function testFormat( $property, $type, $linker, $expected ) {
+
+ $propertyValue = new PropertyValue();
+ $propertyValue->setDataItem( $property );
+
+ $propertyValue->setOption( PropertyValue::OPT_CONTENT_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_USER_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_NO_HIGHLIGHT, true );
+
+ $propertyValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $expected = $this->testEnvironment->replaceNamespaceWithLocalizedText(
+ SMW_NS_PROPERTY,
+ $expected
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $propertyValue, [ $type, $linker ] )
+ );
+ }
+
+ /**
+ * @dataProvider preferredLabelValueProvider
+ */
+ public function testFormatWithPreferredLabel( $property, $preferredLabel, $type, $linker, $expected ) {
+
+ // Ensures the mocked instance is injected and registered with the
+ // PropertyRegistry instance
+ \SMW\PropertyRegistry::clear();
+
+ $this->propertyLabelFinder = $this->getMockBuilder( '\SMW\PropertyLabelFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyLabelFinder->expects( $this->any() )
+ ->method( 'findPropertyListFromLabelByLanguageCode' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->propertyLabelFinder->expects( $this->any() )
+ ->method( 'findPreferredPropertyLabelByLanguageCode' )
+ ->will( $this->returnValue( $preferredLabel ) );
+
+ $this->propertyLabelFinder->expects( $this->any() )
+ ->method( 'searchPropertyIdByLabel' )
+ ->will( $this->returnValue( false ) );
+
+ $this->testEnvironment->registerObject( 'PropertyLabelFinder', $this->propertyLabelFinder );
+
+ $propertyValue = new PropertyValue();
+
+ $propertyValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $propertyValue->setOption( 'smwgDVFeatures', SMW_DV_PROV_LHNT );
+ $propertyValue->setOption( PropertyValue::OPT_CONTENT_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_USER_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_NO_HIGHLIGHT, true );
+
+ $propertyValue->setUserValue( $property );
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $expected = $this->testEnvironment->replaceNamespaceWithLocalizedText(
+ SMW_NS_PROPERTY,
+ $expected
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $propertyValue, [ $type, $linker ] )
+ );
+
+ \SMW\PropertyRegistry::clear();
+ }
+
+ /**
+ * @dataProvider preferredLabelAndCaptionValueProvider
+ */
+ public function testFormatWithPreferredLabelAndCaption( $property, $caption, $preferredLabel, $type, $linker, $expected ) {
+
+ // Ensures the mocked instance is injected and registered with the
+ // PropertyRegistry instance
+ \SMW\PropertyRegistry::clear();
+
+ $this->propertyLabelFinder = $this->getMockBuilder( '\SMW\PropertyLabelFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyLabelFinder->expects( $this->any() )
+ ->method( 'findPropertyListFromLabelByLanguageCode' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->propertyLabelFinder->expects( $this->any() )
+ ->method( 'findPreferredPropertyLabelByLanguageCode' )
+ ->will( $this->returnValue( $preferredLabel ) );
+
+ $this->propertyLabelFinder->expects( $this->any() )
+ ->method( 'searchPropertyIdByLabel' )
+ ->will( $this->returnValue( false ) );
+
+ $this->testEnvironment->registerObject( 'PropertyLabelFinder', $this->propertyLabelFinder );
+
+ $propertyValue = new PropertyValue();
+
+ $propertyValue->setOption( 'smwgDVFeatures', SMW_DV_PROV_LHNT );
+ $propertyValue->setOption( PropertyValue::OPT_CONTENT_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_USER_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_NO_HIGHLIGHT, true );
+
+ $propertyValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $propertyValue->setUserValue( $property );
+ $propertyValue->setCaption( $caption );
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $expected = $this->testEnvironment->replaceNamespaceWithLocalizedText(
+ SMW_NS_PROPERTY,
+ $expected
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $propertyValue, [ $type, $linker ] )
+ );
+
+ \SMW\PropertyRegistry::clear();
+ }
+
+ /**
+ * @dataProvider formattedLabelProvider
+ */
+ public function testFormattedLabelLabel( $property, $linker, $expected ) {
+
+ $propertyValue = new PropertyValue();
+
+ $propertyValue->setOption( PropertyValue::OPT_CONTENT_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_USER_LANGUAGE, 'en' );
+ $propertyValue->setOption( PropertyValue::OPT_NO_HIGHLIGHT, true );
+
+ $propertyValue->setDataItem( $property );
+
+ $propertyValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $expected = $this->testEnvironment->replaceNamespaceWithLocalizedText(
+ SMW_NS_PROPERTY,
+ $expected
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $propertyValue, [ PropertyValue::FORMAT_LABEL, $linker ] )
+ );
+ }
+
+ public function testTryToFormatOnMissingDataValueThrowsException() {
+
+ $instance = new PropertyValueFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->format( PropertyValueFormatter::VALUE );
+ }
+
+ public function propertyValueProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' ),
+ PropertyValueFormatter::VALUE,
+ null,
+ 'Foo'
+ ];
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' ),
+ PropertyValueFormatter::WIKI_SHORT,
+ null,
+ 'Foo'
+ ];
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' ),
+ PropertyValueFormatter::HTML_SHORT,
+ null,
+ 'Foo'
+ ];
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' ),
+ PropertyValueFormatter::WIKI_LONG,
+ null,
+ 'Property:Foo'
+ ];
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' ),
+ PropertyValueFormatter::HTML_LONG,
+ null,
+ 'Property:Foo'
+ ];
+
+ return $provider;
+ }
+
+ public function preferredLabelValueProvider() {
+
+ $linker = 'some';
+
+ $provider[] = [
+ 'Foo',
+ 'Bar',
+ PropertyValueFormatter::VALUE,
+ null,
+ 'Bar'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'Bar',
+ PropertyValueFormatter::WIKI_SHORT,
+ null,
+ 'Bar&nbsp;<span title="Foo"><sup>áµ–</sup></span>'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'Bar',
+ PropertyValueFormatter::HTML_SHORT,
+ null,
+ 'Bar&nbsp;<span title="Foo"><sup>áµ–</sup></span>'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'Bar',
+ PropertyValueFormatter::WIKI_LONG,
+ $linker,
+ '[[:Property:Foo|Bar]]&nbsp;<span title="Foo"><sup>áµ–</sup></span>'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'Bar',
+ PropertyValueFormatter::HTML_LONG,
+ null,
+ 'Property:Foo&nbsp;<span title="Foo"><sup>áµ–</sup></span>'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'Bar with',
+ PropertyValueFormatter::HTML_SHORT,
+ null,
+ 'Bar with&nbsp;<span title="Foo"><sup>áµ–</sup></span>'
+ ];
+
+ return $provider;
+ }
+
+ public function preferredLabelAndCaptionValueProvider() {
+
+ $linker = 'some';
+
+ $provider[] = [
+ 'Foo',
+ false,
+ 'Bar',
+ PropertyValueFormatter::VALUE,
+ null,
+ 'Bar'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ false,
+ 'Bar',
+ PropertyValueFormatter::HTML_SHORT,
+ null,
+ 'Bar'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'Bar with',
+ 'Bar with',
+ PropertyValueFormatter::HTML_SHORT,
+ null,
+ 'Bar with&nbsp;<span title="Foo"><sup>áµ–</sup></span>'
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'Bar&nbsp;with',
+ 'Bar with',
+ PropertyValueFormatter::HTML_SHORT,
+ null,
+ 'Bar&nbsp;with&nbsp;<span title="Foo"><sup>áµ–</sup></span>'
+ ];
+
+ return $provider;
+ }
+
+ public function formattedLabelProvider() {
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property->expects( $this->any() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( \SMWDataItem::TYPE_PROPERTY ) );
+
+ $property->expects( $this->any() )
+ ->method( 'getPreferredLabel' )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ $property->expects( $this->any() )
+ ->method( 'getLabel' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $property->expects( $this->any() )
+ ->method( 'getCanonicalLabel' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $provider[] = [
+ $property,
+ null,
+ '&nbsp;<span style="font-size:small;">(Foo)</span>'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/ReferenceValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/ReferenceValueFormatterTest.php
new file mode 100644
index 00000000..ef0a447b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/ReferenceValueFormatterTest.php
@@ -0,0 +1,224 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ReferenceValue;
+use SMW\DataValues\ValueFormatters\ReferenceValueFormatter;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\ReferenceValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ReferenceValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->stringValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\ReferenceValueFormatter',
+ new ReferenceValueFormatter()
+ );
+ }
+
+ public function testIsFormatterForValidation() {
+
+ $referenceValue = $this->getMockBuilder( '\SMW\DataValues\ReferenceValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ReferenceValueFormatter();
+
+ $this->assertTrue(
+ $instance->isFormatterFor( $referenceValue )
+ );
+ }
+
+ public function testToUseCaptionOutput() {
+
+ $referenceValue = new ReferenceValue();
+ $referenceValue->setCaption( 'ABC' );
+
+ $instance = new ReferenceValueFormatter( $referenceValue );
+
+ $this->assertEquals(
+ 'ABC',
+ $instance->format( ReferenceValueFormatter::WIKI_SHORT )
+ );
+
+ $this->assertEquals(
+ 'ABC',
+ $instance->format( ReferenceValueFormatter::HTML_SHORT )
+ );
+ }
+
+ /**
+ * @dataProvider stringValueProvider
+ */
+ public function testFormat( $suserValue, $type, $linker, $expected ) {
+
+ $referenceValue = new ReferenceValue();
+
+ $referenceValue->setFieldProperties( [
+ $this->dataItemFactory->newDIProperty( 'Foo' ),
+ $this->dataItemFactory->newDIProperty( 'Date' ),
+ $this->dataItemFactory->newDIProperty( 'URL' )
+ ] );
+
+ $referenceValue->setOption( ReferenceValue::OPT_CONTENT_LANGUAGE, 'en' );
+ $referenceValue->setOption( ReferenceValue::OPT_USER_LANGUAGE, 'en' );
+
+ $referenceValue->setUserValue( $suserValue );
+
+ $instance = new ReferenceValueFormatter( $referenceValue );
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->format( $type, $linker )
+ );
+ }
+
+ public function testTryToFormatOnMissingDataValueThrowsException() {
+
+ $instance = new ReferenceValueFormatter();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->format( ReferenceValueFormatter::VALUE );
+ }
+
+ public function stringValueProvider() {
+
+ $provider[] = [
+ 'abc;12;3',
+ ReferenceValueFormatter::VALUE,
+ null,
+ 'Abc'
+ ];
+
+ $provider[] = [
+ 'abc;12;3',
+ ReferenceValueFormatter::VALUE,
+ false,
+ 'Abc;12;3'
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::WIKI_SHORT,
+ null,
+ 'Abc'
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::WIKI_SHORT,
+ false,
+ [
+ 'Abc',
+ 'class="smw-reference smw-reference-indicator smw-highlighter smwttinline"',
+ 'data-title="Reference"',
+ 'title="Date: ?, URL: ?"'
+ ]
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::HTML_SHORT,
+ null,
+ 'Abc'
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::HTML_SHORT,
+ false,
+ [
+ 'Abc',
+ 'class="smw-reference smw-reference-indicator smw-highlighter smwttinline"',
+ 'data-title="Reference"',
+ 'title="Date: ?, URL: ?"'
+ ]
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::WIKI_LONG,
+ null,
+ 'Abc'
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::WIKI_LONG,
+ false,
+ [
+ 'Abc',
+ 'class="smw-reference smw-reference-indicator smw-highlighter smwttinline"',
+ 'data-title="Reference"',
+ 'title="Date: ?, URL: ?"'
+ ]
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::HTML_LONG,
+ null,
+ 'Abc'
+ ];
+
+ $provider[] = [
+ 'abc',
+ ReferenceValueFormatter::HTML_LONG,
+ false,
+ [
+ 'Abc',
+ 'class="smw-reference smw-reference-indicator smw-highlighter smwttinline"',
+ 'data-title="Reference"',
+ 'title="Date: ?, URL: ?"'
+ ]
+ ];
+
+ // Notice: Undefined variable: dataValue in
+ $provider[] = [
+ '?;12;3',
+ ReferenceValueFormatter::VALUE,
+ null,
+ ''
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/StringValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/StringValueFormatterTest.php
new file mode 100644
index 00000000..c12b36ad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/StringValueFormatterTest.php
@@ -0,0 +1,225 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataValues\StringValue;
+use SMW\DataValues\ValueFormatters\StringValueFormatter;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\StringValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class StringValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ StringValueFormatter::class,
+ new StringValueFormatter()
+ );
+ }
+
+ public function testIsFormatterForValidation() {
+
+ $stringValue = $this->getMockBuilder( '\SMW\DataValues\StringValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new StringValueFormatter();
+
+ $this->assertTrue(
+ $instance->isFormatterFor( $stringValue )
+ );
+ }
+
+ public function testToUseCaptionOutput() {
+
+ $stringValue = new StringValue( '_txt' );
+ $stringValue->setCaption( 'ABC[<>]' );
+
+ $instance = new StringValueFormatter();
+
+ $this->assertEquals(
+ 'ABC[<>]',
+ $instance->format( $stringValue, [ StringValueFormatter::WIKI_SHORT ] )
+ );
+
+ $this->assertEquals(
+ 'ABC[&lt;&gt;]',
+ $instance->format( $stringValue, [ StringValueFormatter::HTML_SHORT ] )
+ );
+ }
+
+ /**
+ * @dataProvider stringValueProvider
+ */
+ public function testFormat( $stringUserValue, $type, $linker, $expected ) {
+
+ $stringValue = new StringValue( '_txt' );
+ $stringValue->setUserValue( $stringUserValue );
+
+ $instance = new StringValueFormatter();
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $stringValue, [ $type, $linker ] )
+ );
+ }
+
+ public function testFormatWithReducedLength() {
+
+ // > 255 / Reduced length
+ $text = 'Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede ' .
+ 'lorem nulla justo diam wisi. Libero Nam turpis neque leo scelerisque nec habitasse a lacus mattis. Accumsan ' .
+ 'tincidunt Sed adipiscing nec facilisis tortor Nunc Sed ipsum tellus';
+
+ $expected = 'Lorem ipsum dolor sit amet consectetuer …';
+
+ $stringValue = new StringValue( '_txt' );
+ $stringValue->setUserValue( $text );
+ $stringValue->setOutputFormat( 40 );
+
+ $instance = new StringValueFormatter();
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $stringValue, [ StringValueFormatter::HTML_LONG ] )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $stringValue, [ StringValueFormatter::WIKI_SHORT ] )
+ );
+ }
+
+ public function testTryToFormatOnMissingDataValueThrowsException() {
+
+ $instance = new StringValueFormatter();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->format( StringValueFormatter::VALUE );
+ }
+
+ public function stringValueProvider() {
+
+ $provider[] = [
+ 'foo',
+ StringValueFormatter::VALUE,
+ null,
+ 'foo'
+ ];
+
+ $provider[] = [
+ 'foo',
+ StringValueFormatter::WIKI_SHORT,
+ null,
+ 'foo'
+ ];
+
+ $provider[] = [
+ 'foo',
+ StringValueFormatter::HTML_SHORT,
+ null,
+ 'foo'
+ ];
+
+ $provider[] = [
+ 'foo',
+ StringValueFormatter::WIKI_LONG,
+ null,
+ 'foo'
+ ];
+
+ $provider[] = [
+ 'foo',
+ StringValueFormatter::HTML_LONG,
+ null,
+ 'foo'
+ ];
+
+ // > 255
+ $text = 'Lorem ipsum dolor sit amet consectetuer justo Nam quis lobortis vel. Sapien nulla enim Lorem enim pede ' .
+ 'lorem nulla justo diam wisi. Libero Nam turpis neque leo scelerisque nec habitasse a lacus mattis. Accumsan ' .
+ 'tincidunt Sed adipiscing nec facilisis tortor Nunc Sed ipsum tellus';
+
+ $provider[] = [
+ $text,
+ StringValueFormatter::HTML_LONG,
+ null,
+ 'Lorem ipsum dolor sit amet consectetuer ju <span class="smwwarning">…</span> nec facilisis tortor Nunc Sed ipsum tellus'
+ ];
+
+ $provider[] = [
+ $text,
+ StringValueFormatter::WIKI_LONG,
+ null,
+ 'Lorem ipsum dolor sit amet consectetuer ju <span class="smwwarning">…</span> nec facilisis tortor Nunc Sed ipsum tellus'
+ ];
+
+ // Avoid breaking links
+ $text = 'Lorem ipsum dolor sit amet consectetuer [[justo Nam quis lobortis vel]]. Sapien nulla enim Lorem enim pede ' .
+ 'lorem nulla justo diam wisi. Libero Nam turpis neque leo scelerisque nec habitasse a lacus mattis. Accumsan ' .
+ 'tincidunt [[Sed adipiscing nec]] facilisis tortor Nunc Sed ipsum tellus';
+
+ $provider[] = [
+ $text,
+ StringValueFormatter::HTML_LONG,
+ null,
+ 'Lorem ipsum dolor sit amet consectetuer [[justo Nam quis lobortis vel]] <span class="smwwarning">…</span> [[Sed adipiscing nec]] facilisis tortor Nunc Sed ipsum tellus'
+ ];
+
+ // XMLContentEncode
+ $provider[] = [
+ '<foo>',
+ StringValueFormatter::HTML_LONG,
+ null,
+ '&lt;foo&gt;'
+ ];
+
+ $provider[] = [
+ '<foo>',
+ StringValueFormatter::HTML_SHORT,
+ null,
+ '&lt;foo&gt;'
+ ];
+
+ $provider[] = [
+ '*Foo',
+ StringValueFormatter::WIKI_LONG,
+ null,
+ "\n" . '*Foo' . "\n"
+ ];
+
+ $provider[] = [
+ '#Foo',
+ StringValueFormatter::WIKI_LONG,
+ null,
+ "\n" . '#Foo' . "\n"
+ ];
+
+ $provider[] = [
+ ':Foo',
+ StringValueFormatter::WIKI_LONG,
+ null,
+ "\n" . ':Foo' . "\n"
+ ];
+
+ $provider[] = [
+ '* Foo',
+ StringValueFormatter::HTML_LONG,
+ null,
+ "\n" . '* Foo' . "\n"
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/TimeValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/TimeValueFormatterTest.php
new file mode 100644
index 00000000..4d174ea9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueFormatters/TimeValueFormatterTest.php
@@ -0,0 +1,548 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueFormatters;
+
+use SMW\DataValues\ValueFormatters\TimeValueFormatter;
+use SMW\DataValues\ValueParsers\TimeValueParser;
+use SMWTimeValue as TimeValue;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueFormatters\TimeValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class TimeValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $dataValueServiceFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( new TimeValueParser() ) );
+
+ $this->dataValueServiceFactory->expects( $this->any() )
+ ->method( 'getConstraintValueValidator' )
+ ->will( $this->returnValue( $constraintValueValidator ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueFormatters\TimeValueFormatter',
+ new TimeValueFormatter()
+ );
+ }
+
+ public function testIsFormatterForValidation() {
+
+ $timeValue = $this->getMockBuilder( '\SMWTimeValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new TimeValueFormatter();
+
+ $this->assertTrue(
+ $instance->isFormatterFor( $timeValue )
+ );
+ }
+
+ public function testTryToFormatOnMissingDataValueThrowsException() {
+
+ $instance = new TimeValueFormatter();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->format( TimeValueFormatter::VALUE );
+ }
+
+ public function testSetGetOptionValue() {
+
+ $instance = new TimeValueFormatter();
+ $instance->setOption( 'Foo', 1001 );
+
+ $this->assertEquals(
+ 1001,
+ $instance->getOption( 'Foo' )
+ );
+ }
+
+ public function testToUseCaptionOutput() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setCaption( 'ABC[<>]' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ 'ABC[<>]',
+ $instance->format( TimeValueFormatter::WIKI_SHORT )
+ );
+ }
+
+ /**
+ * @dataProvider timeInputProvider
+ */
+ public function testFormat( $timeUserValue, $type, $format, $linker, $languageCode, $expected ) {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( $timeUserValue );
+
+ $timeValue->setOutputFormat( $format );
+
+ $timeValue->setOption( 'user.language', $languageCode );
+ $timeValue->setOption( 'content.language', $languageCode );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ $expected,
+ $instance->format( $type, $linker )
+ );
+ }
+
+ public function testGetISO8601DateForMinDefault() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2000' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2000-01-01',
+ $instance->getISO8601Date( true )
+ );
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2000-02-23 12:02' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2000-02-23T12:02:00',
+ $instance->getISO8601Date( true )
+ );
+ }
+
+ public function testGetISO8601DateForMaxDefault() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2000' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2000-12-31',
+ $instance->getISO8601Date( false )
+ );
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2000-02-23 12:02' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2000-02-23T12:02:00',
+ $instance->getISO8601Date( false )
+ );
+ }
+
+ public function testGetCaptionFromDataItemForPositiveYearWithEraMarker() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2000 AD' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ 'AD 2000',
+ $instance->getCaptionFromDataItem( $timeValue->getDataItem() )
+ );
+ }
+
+ public function testLeapYear() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2016-02-29' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+
+ $this->assertEquals(
+ '2016-02-29',
+ $instance->getISO8601Date()
+ );
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2016-02' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2016-02-29',
+ $instance->getISO8601Date( false )
+ );
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2015-02' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2015-02-28',
+ $instance->getISO8601Date( false )
+ );
+ }
+
+ public function testInvalidLeapYear() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2015-02-29' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testMediaWikiDate_WithDifferentLanguage() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2015-02-28' );
+ $timeValue->setOption( 'user.language', 'en' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '28 February 2015',
+ $instance->getMediaWikiDate()
+ );
+
+ $timeValue->setOption( 'user.language', 'ja' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2015年2月28日 (土)',
+ $instance->getMediaWikiDate()
+ );
+ }
+
+ public function testLOCLOutputFormat() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2015-02-28' );
+
+ $timeValue->setOption( TimeValue::OPT_USER_LANGUAGE, 'en' );
+ $timeValue->setOutputFormat( 'LOCL' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ $instance->format( TimeValueFormatter::WIKI_LONG ),
+ $instance->getLocalizedFormat( $timeValue->getDataItem() )
+ );
+
+ $this->assertEquals(
+ $instance->format( TimeValueFormatter::HTML_LONG ),
+ $instance->getLocalizedFormat( $timeValue->getDataItem() )
+ );
+ }
+
+ public function testLOCLOutputFormatWithSpecificAnnotatedLanguage() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2015-02-28' );
+
+ $timeValue->setOption( TimeValue::OPT_USER_LANGUAGE, 'en' );
+ $timeValue->setOutputFormat( 'LOCL@ja' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2015年2月28日 (土)',
+ $instance->getLocalizedFormat( $timeValue->getDataItem() )
+ );
+ }
+
+ public function testLOCLOutputFormatWithTimeZone() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2015-02-28 12:12:00 A' );
+
+ $timeValue->setOption( TimeValue::OPT_USER_LANGUAGE, 'en' );
+ $timeValue->setOutputFormat( 'LOCL#TZ' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '12:12:00 A, 28 February 2015',
+ $instance->format( TimeValueFormatter::HTML_LONG )
+ );
+
+ $this->assertEquals(
+ '2015-02-28 12:12:00 A',
+ $instance->format( TimeValueFormatter::WIKI_SHORT )
+ );
+ }
+
+ public function testLOCLOutputFormatWithTimeZoneOnSpecificAnnotatedLanguage() {
+
+ $timeValue = new TimeValue( '_dat' );
+ $timeValue->setDataValueServiceFactory(
+ $this->dataValueServiceFactory
+ );
+
+ $timeValue->setUserValue( '2015-02-28 12:12:00 A' );
+
+ $timeValue->setOption( TimeValue::OPT_USER_LANGUAGE, 'en' );
+ $timeValue->setOutputFormat( 'LOCL@ja#TZ' );
+
+ $instance = new TimeValueFormatter( $timeValue );
+
+ $this->assertEquals(
+ '2015年2月28日 (土) 12:12:00 A',
+ $instance->format( TimeValueFormatter::HTML_LONG )
+ );
+
+ $this->assertEquals(
+ '2015-02-28 12:12:00 A',
+ $instance->format( TimeValueFormatter::WIKI_SHORT )
+ );
+ }
+
+ public function timeInputProvider() {
+
+ #0
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::VALUE,
+ '',
+ null,
+ '',
+ '2000'
+ ];
+
+ #1
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::VALUE,
+ 'ISO',
+ null,
+ '',
+ '2000'
+ ];
+
+ #2
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::WIKI_SHORT,
+ 'ISO',
+ null,
+ '',
+ '2000'
+ ];
+
+ #3
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::HTML_SHORT,
+ 'ISO',
+ null,
+ '',
+ '2000'
+ ];
+
+ #4
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::WIKI_LONG,
+ 'ISO',
+ null,
+ '',
+ '2000-01-01'
+ ];
+
+ #5
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::HTML_LONG,
+ 'ISO',
+ null,
+ '',
+ '2000-01-01'
+ ];
+
+ #6
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::WIKI_LONG,
+ 'MEDIAWIKI',
+ null,
+ '',
+ '2000'
+ ];
+
+ #7
+ $provider[] = [
+ '2000',
+ TimeValueFormatter::HTML_LONG,
+ 'MEDIAWIKI',
+ null,
+ '',
+ '2000'
+ ];
+
+ #8
+ $provider[] = [
+ '2000-02',
+ TimeValueFormatter::VALUE,
+ '',
+ null,
+ '',
+ '2000-02'
+ ];
+
+ #9
+ $provider[] = [
+ '2000-02',
+ TimeValueFormatter::VALUE,
+ 'ISO',
+ null,
+ '',
+ '2000-02'
+ ];
+
+ #10
+ $provider[] = [
+ '2000-02',
+ TimeValueFormatter::WIKI_SHORT,
+ '',
+ null,
+ '',
+ '2000-02'
+ ];
+
+ #11
+ $provider[] = [
+ '2000-02',
+ TimeValueFormatter::HTML_SHORT,
+ 'ISO',
+ null,
+ '',
+ '2000-02'
+ ];
+
+ #12
+ $provider[] = [
+ '2000-02',
+ TimeValueFormatter::WIKI_LONG,
+ 'ISO',
+ null,
+ '',
+ '2000-02-01'
+ ];
+
+ #13
+ $provider[] = [
+ '2000-02',
+ TimeValueFormatter::HTML_LONG,
+ 'ISO',
+ null,
+ '',
+ '2000-02-01'
+ ];
+
+ #14
+ $provider[] = [
+ '2000-02',
+ TimeValueFormatter::HTML_LONG,
+ 'LOCL',
+ null,
+ 'en',
+ 'February 2000'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsListValueParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsListValueParserTest.php
new file mode 100644
index 00000000..71c129a9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsListValueParserTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueParsers;
+
+use SMW\DataValues\ValueParsers\AllowsListValueParser;
+
+/**
+ * @covers \SMW\DataValues\ValueParsers\AllowsListValueParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class AllowsListValueParserTest extends \PHPUnit_Framework_TestCase {
+
+ private $mediaWikiNsContentReader;
+
+ protected function setUp() {
+ $this->mediaWikiNsContentReader = $this->getMockBuilder( '\SMW\MediaWiki\MediaWikiNsContentReader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueParsers\AllowsListValueParser',
+ new AllowsListValueParser( $this->mediaWikiNsContentReader )
+ );
+ }
+
+ public function testParseAndMatchFromResource() {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( " \n*Foo\n**Foobar|bar\n" ) );
+
+ $instance = new AllowsListValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $this->assertEquals(
+ [
+ 'Foo' => 'Foo',
+ 'Foobar' => 'bar'
+ ],
+ $instance->parse( 'Bar' )
+ );
+ }
+
+ public function testParseAndMatchFromJSON() {
+
+ $contents = json_encode( [ 'Foo' => 'Foo', 'Foobar' => 'fooooo bar' ] );
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new AllowsListValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $instance->clear();
+
+ $this->assertEquals(
+ [
+ 'Foo' => 'Foo',
+ 'Foobar' => 'fooooo bar'
+ ],
+ $instance->parse( 'Bar' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsPatternValueParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsPatternValueParserTest.php
new file mode 100644
index 00000000..4c8c23dd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/AllowsPatternValueParserTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueParsers;
+
+use SMW\DataValues\ValueParsers\AllowsPatternValueParser;
+
+/**
+ * @covers \SMW\DataValues\ValueParsers\AllowsPatternValueParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class AllowsPatternValueParserTest extends \PHPUnit_Framework_TestCase {
+
+ private $mediaWikiNsContentReader;
+
+ protected function setUp() {
+ $this->mediaWikiNsContentReader = $this->getMockBuilder( '\SMW\MediaWiki\MediaWikiNsContentReader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueParsers\AllowsPatternValueParser',
+ new AllowsPatternValueParser( $this->mediaWikiNsContentReader )
+ );
+ }
+
+ public function testParseAndMatchFromResource() {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( " \nFoo|^(Bar|Foo bar)$\n Bar|^(ABC|DEF)$\n" ) );
+
+ $instance = new AllowsPatternValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $this->assertEquals(
+ '^(ABC|DEF)$',
+ $instance->parse( 'Bar' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/ImportValueParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/ImportValueParserTest.php
new file mode 100644
index 00000000..43682acb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/ImportValueParserTest.php
@@ -0,0 +1,223 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueParsers;
+
+use SMW\DataValues\ImportValue;
+use SMW\DataValues\ValueParsers\ImportValueParser;
+
+/**
+ * @covers \SMW\DataValues\ValueParsers\ImportValueParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ImportValueParserTest extends \PHPUnit_Framework_TestCase {
+
+ private $mediaWikiNsContentReader;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mediaWikiNsContentReader = $this->getMockBuilder( '\SMW\MediaWiki\MediaWikiNsContentReader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ImportValueParser::class,
+ new ImportValueParser( $this->mediaWikiNsContentReader )
+ );
+ }
+
+ public function testTryParseForInvalidValueFormat() {
+
+ $instance = new ImportValueParser( $this->mediaWikiNsContentReader );
+ $instance->parse( 'incorrectFormat' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testTryParseForValidValueFormatErroredByNonExistingImportEntry() {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->with( $this->equalTo( ImportValue::IMPORT_PREFIX . 'Foo' ) )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new ImportValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $instance->parse( 'Foo:bar' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ /**
+ * @dataProvider invalidUriContent
+ */
+ public function testTryParseForValidValueFormatErroredByUriMismatch( $content ) {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $content ) );
+
+ $instance = new ImportValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $instance->parse( 'Foo:bar' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ /**
+ * @dataProvider invalidTypeContent
+ */
+ public function testTryParseForValidValueFormatErroredByTypeMismatch( $content, $typelist ) {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $content ) );
+
+ $instance = new ImportValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $instance->parse( 'Foo:bar' );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ /**
+ * @dataProvider validMatchTypeContent
+ */
+ public function testParseForValidValueToMatchType( $content, $parseValue, $expected ) {
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $content ) );
+
+ $instance = new ImportValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $result = $instance->parse( $parseValue );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+
+ foreach ( $result as $key => $value ) {
+ $this->assertEquals(
+ $expected[$key],
+ $value
+ );
+ }
+ }
+
+ public function invalidUriContent() {
+
+ $provider[] = [
+ ''
+ ];
+
+ // Missing head
+ $provider[] = [
+ "Foo\n name|Type:Text\n"
+ ];
+
+ return $provider;
+ }
+
+ public function invalidTypeContent() {
+
+ // Url missing
+ $provider[] = [
+ '|[http://www.foaf-project.org/ Friend Of A Friend]\n name',
+ []
+ ];
+
+ // Type missing
+ $provider[] = [
+ 'http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name',
+ []
+ ];
+
+ // Cannot match section name
+ $provider[] = [
+ "http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name|Type:Text\n",
+ [ 'name' => 'Type:Text' ]
+ ];
+
+ $provider[] = [
+ '',
+ []
+ ];
+
+ $provider[] = [
+ ' ',
+ []
+ ];
+
+ return $provider;
+ }
+
+ public function validMatchTypeContent() {
+
+ #0
+ $provider[] = [
+ "http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name|Type:Text\n",
+ 'Foaf:name',
+ [
+ 'Foaf',
+ 'name',
+ 'http://xmlns.com/foaf/0.1/',
+ '[http://www.foaf-project.org/ Friend Of A Friend]',
+ 'Type:Text'
+ ]
+ ];
+
+ #1
+ $provider[] = [
+ " http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n name|Type:Text\n",
+ 'Foaf:name',
+ [
+ 'Foaf',
+ 'name',
+ 'http://xmlns.com/foaf/0.1/',
+ '[http://www.foaf-project.org/ Friend Of A Friend]',
+ 'Type:Text'
+ ]
+ ];
+
+ #2 mbox_sha1sum
+ $provider[] = [
+ " http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]\n mbox_sha1sum|Type:Text\n",
+ 'Foaf:mbox_sha1sum',
+ [
+ 'Foaf',
+ 'mbox_sha1sum',
+ 'http://xmlns.com/foaf/0.1/',
+ '[http://www.foaf-project.org/ Friend Of A Friend]',
+ 'Type:Text'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/MonolingualTextValueParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/MonolingualTextValueParserTest.php
new file mode 100644
index 00000000..2025d29a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/MonolingualTextValueParserTest.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueParsers;
+
+use SMW\DataValues\ValueParsers\MonolingualTextValueParser;
+
+/**
+ * @covers \SMW\DataValues\ValueParsers\MonolingualTextValueParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class MonolingualTextValueParserTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueParsers\MonolingualTextValueParser',
+ new MonolingualTextValueParser()
+ );
+ }
+
+ /**
+ * @dataProvider fullStringProvider
+ */
+ public function testFullParsableString( $value, $expectedText, $expectedLanguageCode ) {
+
+ $instance = new MonolingualTextValueParser();
+ list( $text, $languageCode ) = $instance->parse( $value );
+
+ $this->assertEquals(
+ $expectedText,
+ $text
+ );
+
+ $this->assertEquals(
+ $expectedLanguageCode,
+ $languageCode
+ );
+ }
+
+ public function testParsableStringWithMissingLanguageCode() {
+
+ $instance = new MonolingualTextValueParser();
+ list( $text, $languageCode ) = $instance->parse( 'FooBar' );
+
+ $this->assertEquals(
+ 'FooBar',
+ $text
+ );
+ }
+
+ public function fullStringProvider() {
+
+ $provider[] = [
+ 'Foo@EN',
+ 'Foo',
+ 'en'
+ ];
+
+ $provider[] = [
+ 'testWith@example.org@zh-hans',
+ 'testWith@example.org',
+ 'zh-Hans'
+ ];
+
+ $provider[] = [
+ [ 'EN' =>'Foo' ],
+ 'Foo',
+ 'en'
+ ];
+
+ $provider[] = [
+ [ 'EN', 'Foo' ],
+ 'Foo',
+ ''
+ ];
+
+ $provider[] = [
+ [ 'EN', [] ],
+ '',
+ ''
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/PropertyValueParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/PropertyValueParserTest.php
new file mode 100644
index 00000000..ef475a98
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/PropertyValueParserTest.php
@@ -0,0 +1,171 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueParsers;
+
+use SMW\DataValues\ValueParsers\PropertyValueParser;
+
+/**
+ * @covers \SMW\DataValues\ValueParsers\PropertyValueParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyValueParserTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertyValueParser::class,
+ new PropertyValueParser()
+ );
+ }
+
+ /**
+ * @dataProvider nameProvider
+ */
+ public function testParse( $value, $invalidCharacterList, $expectedPropertyName, $expectedInverse ) {
+
+ $instance = new PropertyValueParser();
+ $instance->setInvalidCharacterList(
+ $invalidCharacterList
+ );
+
+ list( $propertyName, $capitalizedName, $inverse ) = $instance->parse( $value );
+
+ $this->assertSame(
+ $expectedPropertyName,
+ $propertyName
+ );
+
+ $this->assertSame(
+ $expectedInverse,
+ $inverse
+ );
+ }
+
+ public function testEnforceFirstCharUpperCase() {
+
+ $instance = new PropertyValueParser();
+ $instance->isCapitalLinks( false );
+ $instance->reqCapitalizedFirstChar( true );
+
+ list( $propertyName, $capitalizedName, $inverse ) = $instance->parse( 'foo' );
+
+ $this->assertSame(
+ 'foo',
+ $propertyName
+ );
+
+ $this->assertSame(
+ 'Foo',
+ $capitalizedName
+ );
+ }
+
+ public function nameProvider() {
+
+ $provider[] = [
+ 'Foo',
+ [],
+ 'Foo',
+ false
+ ];
+
+ $provider[] = [
+ '[ Foo',
+ [],
+ 'Foo',
+ false
+ ];
+
+ $provider[] = [
+ '[Foo',
+ [],
+ 'Foo',
+ false
+ ];
+
+ $provider[] = [
+ 'Foo ]',
+ [],
+ 'Foo',
+ false
+ ];
+
+ $provider[] = [
+ 'Foo]',
+ [],
+ 'Foo',
+ false
+ ];
+
+ $provider[] = [
+ '-Foo',
+ [],
+ 'Foo',
+ true
+ ];
+
+ $provider[] = [
+ '<Foo>',
+ [ '<', '>' ],
+ null,
+ null
+ ];
+
+ $provider[] = [
+ '<Foo-<Bar>',
+ [ '<', '>' ],
+ null,
+ null
+ ];
+
+ $provider[] = [
+ 'Foo-<Bar',
+ [ '<', '>' ],
+ 'Foo-',
+ false
+ ];
+
+ $provider[] = [
+ 'Foo#Bar',
+ [],
+ null,
+ null
+ ];
+
+ $provider[] = [
+ 'Foo|Bar',
+ [ '|' ],
+ null,
+ null
+ ];
+
+ $provider[] = [
+ 'Foo.Bar',
+ [],
+ null,
+ null
+ ];
+
+ $provider[] = [
+ 'Foo[Bar',
+ [ '[', ']' ],
+ null,
+ null
+ ];
+
+ $provider[] = [
+ 'Foo]Bar',
+ [ '[', ']' ],
+ null,
+ null
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/TimeValueParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/TimeValueParserTest.php
new file mode 100644
index 00000000..732097a5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueParsers/TimeValueParserTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueParsers;
+
+use SMW\DataValues\Time\Components;
+use SMW\DataValues\ValueParsers\TimeValueParser;
+
+/**
+ * @covers \SMW\DataValues\ValueParsers\TimeValueParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TimeValueParserTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TimeValueParser::class,
+ new TimeValueParser()
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testParse( $value, $expected, $errors ) {
+
+ $instance = new TimeValueParser();
+
+ $this->assertEquals(
+ new Components( $expected ),
+ $instance->parse( $value )
+ );
+
+ $this->assertEquals(
+ $errors,
+ $instance->getErrors()
+ );
+ }
+
+ public function valueProvider() {
+
+ yield [
+ '1 Jan 1970',
+ [
+ 'value' => '1 Jan 1970',
+ 'datecomponents' => [
+ '1', 'Jan', '1970'
+ ],
+ 'calendarmodel' => false,
+ 'era' => false,
+ 'hours' => false,
+ 'minutes' => false,
+ 'seconds' => false,
+ 'microseconds' => false,
+ 'timeoffset' => 0,
+ 'timezone' => false
+ ],
+ []
+ ];
+
+ // JD value
+ yield [
+ '2458119.500000',
+ [
+ 'value' => '2458119.500000',
+ 'datecomponents' => [
+ '2458119', '500000'
+ ],
+ 'calendarmodel' => 'JD',
+ 'era' => false,
+ 'hours' => false,
+ 'minutes' => false,
+ 'seconds' => false,
+ 'microseconds' => false,
+ 'timeoffset' => 0,
+ 'timezone' => false
+ ],
+ []
+ ];
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/AllowsListConstraintValueValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/AllowsListConstraintValueValidatorTest.php
new file mode 100644
index 00000000..20ef32e1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/AllowsListConstraintValueValidatorTest.php
@@ -0,0 +1,411 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueValidators;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ValueValidators\AllowsListConstraintValueValidator;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\ValueValidators\AllowsListConstraintValueValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class AllowsListConstraintValueValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+ private $allowsListValueParser;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->allowsListValueParser = $this->getMockBuilder( '\SMW\DataValues\ValueParsers\AllowsListValueParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ AllowsListConstraintValueValidator::class,
+ new AllowsListConstraintValueValidator( $this->allowsListValueParser, $this->propertySpecificationLookup )
+ );
+ }
+
+ public function testIsAllowedValueOnTheValidatedDataValue() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'ValidAllowedValue' );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedValues' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBlob( 'Foo' ) ] ) );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedListValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getTypeID' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Foo' ) ) );
+
+ $instance = new AllowsListConstraintValueValidator(
+ $this->allowsListValueParser,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->validate( $dataValue );
+
+ $this->assertFalse(
+ $instance->hasConstraintViolation()
+ );
+ }
+
+ public function testIsNotAllowedValueOnTheValidatedDataValue() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'InvalidAllowedValue' );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedValues' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBlob( 'NOTALLOWED' ) ] ) );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedListValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getTypeID' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Foo' ) ) );
+
+ $instance = new AllowsListConstraintValueValidator(
+ $this->allowsListValueParser,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->validate( $dataValue );
+
+ $this->assertTrue(
+ $instance->hasConstraintViolation()
+ );
+ }
+
+ public function testIsNotAllowedValueWithShortenedLongList() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'InvalidAllowedValue' );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedValues' )
+ ->will( $this->returnValue(
+ [
+ $this->dataItemFactory->newDIBlob( 'VAL1' ),
+ $this->dataItemFactory->newDIBlob( 'VAL2' ),
+ $this->dataItemFactory->newDIBlob( 'VAL2' ),
+ $this->dataItemFactory->newDIBlob( 'VAL3' ),
+ $this->dataItemFactory->newDIBlob( 'VAL4' ),
+ $this->dataItemFactory->newDIBlob( 'VAL5' ),
+ $this->dataItemFactory->newDIBlob( 'VAL6' ),
+ $this->dataItemFactory->newDIBlob( 'VAL7' ),
+ $this->dataItemFactory->newDIBlob( 'VAL8' ),
+ $this->dataItemFactory->newDIBlob( 'VAL9' ),
+ $this->dataItemFactory->newDIBlob( 'VAL0' ),
+ $this->dataItemFactory->newDIBlob( 'VAL11' ) ] ) );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedListValues' )
+ ->will( $this->returnValue( [ ] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getTypeID' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Foo' ) ) );
+
+ $instance = new AllowsListConstraintValueValidator(
+ $this->allowsListValueParser,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->validate( $dataValue );
+
+ $this->assertEquals(
+ [
+ 'a3cb94437b0f3619eaebd527123a4558' => '[8,"smw-datavalue-constraint-error-allows-value-list","","VAL1, VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL8, VAL9, VAL0, ...","InvalidAllowedValue"]'
+ ],
+ $dataValue->getErrors()
+ );
+ }
+
+ public function testIsAllowedValueFromCombinedList() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'ValidAllowedValue' );
+
+ $this->allowsListValueParser->expects( $this->any() )
+ ->method( 'parse' )
+ ->will( $this->onConsecutiveCalls( [ 'Foo' => 'foo' ], [ 'Bar' => 'bar' ] ) );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedListValues' )
+ ->will( $this->returnValue( [
+ $this->dataItemFactory->newDIBlob( 'list_foo' ),
+ $this->dataItemFactory->newDIBlob( 'list_bar' ) ] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getTypeID' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar' ) ) );
+
+ $instance = new AllowsListConstraintValueValidator(
+ $this->allowsListValueParser,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->validate( $dataValue );
+
+ $this->assertFalse(
+ $instance->hasConstraintViolation()
+ );
+ }
+
+ /**
+ * @dataProvider rangeProvider
+ */
+ public function testCompareNumberRange( $allowsValue, $dataItem, $expected ) {
+
+ $property = $this->dataItemFactory->newDIProperty( 'InvalidAllowedValue' );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedValues' )
+ ->will( $this->returnValue( $allowsValue ) );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedListValues' )
+ ->will( $this->returnValue( [ ] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getTypeID', 'getWikiValue' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_num' ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getWikiValue' )
+ ->will( $this->returnValue( $dataItem->getNumber() ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItem ) );
+
+ $instance = new AllowsListConstraintValueValidator(
+ $this->allowsListValueParser,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->validate( $dataValue );
+
+ $this->assertEquals(
+ $expected,
+ $dataValue->getErrors()
+ );
+ }
+
+ public function rangeProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ // Combinations do test that the order for a range and a discrete value
+ // doesn't matter
+
+ // Range
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '>1' ),
+ $dataItemFactory->newDIBlob( '<4' )
+ ],
+ $dataItemFactory->newDINumber( 3 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '>1' ),
+ $dataItemFactory->newDIBlob( '5' ),
+ $dataItemFactory->newDIBlob( '<4' )
+ ],
+ $dataItemFactory->newDINumber( 5 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '<4' ),
+ $dataItemFactory->newDIBlob( '>1' ),
+ $dataItemFactory->newDIBlob( '5' ),
+ ],
+ $dataItemFactory->newDINumber( 5 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '5' ),
+ $dataItemFactory->newDIBlob( '<4' ),
+ $dataItemFactory->newDIBlob( '>1' ),
+ ],
+ $dataItemFactory->newDINumber( 5 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '>1' ),
+ $dataItemFactory->newDIBlob( '<4' )
+ ],
+ $dataItemFactory->newDINumber( 5 ),
+ [
+ '9b7a08f3296c976852260443ff290b16' => '[8,"smw-datavalue-constraint-error-allows-value-range","5","<4","InvalidAllowedValue"]'
+ ]
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '<4' ),
+ $dataItemFactory->newDIBlob( '>1' )
+ ],
+ $dataItemFactory->newDINumber( 5 ),
+ [
+ '28e3bb64ee1452b03e0e2afac787c010' => '[8,"smw-datavalue-constraint-error-allows-value-range","5","<4, >1","InvalidAllowedValue"]'
+ ]
+ ];
+
+ // Bounds
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '1...10' )
+ ],
+ $dataItemFactory->newDINumber( 5 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '1...10' )
+ ],
+ $dataItemFactory->newDINumber( 10 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '1...10' ),
+ $dataItemFactory->newDIBlob( '15' )
+ ],
+ $dataItemFactory->newDINumber( 15 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '1...10' ),
+ $dataItemFactory->newDIBlob( '50...100' )
+ ],
+ $dataItemFactory->newDINumber( 100 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '<200' ),
+ $dataItemFactory->newDIBlob( '1...10' ),
+ $dataItemFactory->newDIBlob( '15' ),
+ $dataItemFactory->newDIBlob( '>100' )
+ ],
+ $dataItemFactory->newDINumber( 101 ),
+ []
+ ];
+
+ yield [
+ [
+ $dataItemFactory->newDIBlob( '1...10' )
+ ],
+ $dataItemFactory->newDINumber( 15 ),
+ [
+ '437bd520d612acf0ccb7f460c2784275' => '[8,"smw-datavalue-constraint-error-allows-value-range","15","1...10","InvalidAllowedValue"]'
+ ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/CompoundConstraintValueValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/CompoundConstraintValueValidatorTest.php
new file mode 100644
index 00000000..3b3a7054
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/CompoundConstraintValueValidatorTest.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueValidators;
+
+use SMW\DataValues\ValueValidators\CompoundConstraintValueValidator;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\DataValues\ValueValidators\CompoundConstraintValueValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class CompoundConstraintValueValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueValidators\CompoundConstraintValueValidator',
+ new CompoundConstraintValueValidator()
+ );
+ }
+
+ public function testHasConstraintViolation() {
+
+ $constraintValueValidator = $this->getMockBuilder( '\SMW\DataValues\ValueValidators\ConstraintValueValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $constraintValueValidator->expects( $this->once() )
+ ->method( 'validate' )
+ ->with( $this->equalTo( 'Foo' ) );
+
+ $constraintValueValidator->expects( $this->once() )
+ ->method( 'hasConstraintViolation' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new CompoundConstraintValueValidator();
+ $instance->registerConstraintValueValidator( $constraintValueValidator );
+
+ $instance->validate( 'Foo' );
+
+ $this->assertTrue(
+ $instance->hasConstraintViolation()
+ );
+ }
+
+ public function testMissingConstraintValueValidatorRegThrowsException() {
+
+ $instance = new CompoundConstraintValueValidator();
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->validate( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PatternConstraintValueValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PatternConstraintValueValidatorTest.php
new file mode 100644
index 00000000..257043c7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PatternConstraintValueValidatorTest.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueValidators;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ValueParsers\AllowsPatternValueParser;
+use SMW\DataValues\ValueValidators\PatternConstraintValueValidator;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\ValueValidators\PatternConstraintValueValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class PatternConstraintValueValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+ private $mediaWikiNsContentReader;
+ private $allowsPatternValueParser;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->mediaWikiNsContentReader = $this->getMockBuilder( '\SMW\MediaWiki\MediaWikiNsContentReader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'MediaWikiNsContentReader', $this->mediaWikiNsContentReader );
+
+ $this->allowsPatternValueParser = new AllowsPatternValueParser(
+ $this->mediaWikiNsContentReader
+ );
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueValidators\PatternConstraintValueValidator',
+ new PatternConstraintValueValidator( $this->allowsPatternValueParser )
+ );
+ }
+
+ /**
+ * @dataProvider allowedPatternProvider
+ */
+ public function testPatternUsingMockedDataValue( $allowedPattern, $testString, $expectedConstraintViolation ) {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Has allowed pattern' );
+
+ $this->mediaWikiNsContentReader->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $allowedPattern ) );
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getAllowedPatternBy' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getTypeID' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( $testString ) ) );
+
+ $instance = new PatternConstraintValueValidator(
+ $this->allowsPatternValueParser
+ );
+
+ $dataValue->setOption( 'smwgDVFeatures', SMW_DV_PVAP );
+
+ $instance->validate( $dataValue );
+
+ $this->assertEquals(
+ $expectedConstraintViolation,
+ $instance->hasConstraintViolation()
+ );
+ }
+
+ public function allowedPatternProvider() {
+
+ $provider[] = [
+ " \nFoo|^(Bar|Foo bar)$/e\n",
+ 'Foo bar',
+ false
+ ];
+
+ #1 valid
+ $provider[] = [
+ " \nFoo|(ev\d{7}\d{4})|((tt|nm|ch|co|ev)\d{7})\n",
+ 'tt0042876',
+ false
+ ];
+
+ #2 uses '/\'
+ $provider[] = [
+ " \nFoo|(ev\d{7}/\d{4})|((tt|nm|ch|co|ev)\d{7})\n",
+ 'tt0042876',
+ false
+ ];
+
+ #3 "Compilation failed: missing )", suppress error
+ $provider[] = [
+ " \nFoo|(ev\d{7}\d{4})|((tt|nm|ch|co|ev)\d{7}\n",
+ 'Foo',
+ true
+ ];
+
+ #4
+ $provider[] = [
+ " \nFoo|\d{8}\n",
+ '00564222',
+ false
+ ];
+
+ #5
+ $provider[] = [
+ " \nFoo|/\d{8}\n",
+ '00564222',
+ false
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PropertySpecificationConstraintValueValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PropertySpecificationConstraintValueValidatorTest.php
new file mode 100644
index 00000000..13e071f6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/PropertySpecificationConstraintValueValidatorTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueValidators;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\DataValues\ValueValidators\PropertySpecificationConstraintValueValidator;
+
+/**
+ * @covers \SMW\DataValues\ValueValidators\PropertySpecificationConstraintValueValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertySpecificationConstraintValueValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $dataValueFactory;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\DataValues\ValueValidators\PropertySpecificationConstraintValueValidator',
+ new PropertySpecificationConstraintValueValidator()
+ );
+ }
+
+ public function testHasNoConstraintViolationOnNonRelatedValue() {
+
+ $instance = new PropertySpecificationConstraintValueValidator();
+ $instance->validate( 'Foo' );
+
+ $this->assertFalse(
+ $instance->hasConstraintViolation()
+ );
+ }
+
+ public function testHasNoConstraintViolationOnDisabledPreferredLabelPropertyButWithError() {
+
+ $dataValue = $this->dataValueFactory->newDataValueByProperty(
+ $this->dataItemFactory->newDIProperty( '_PPLB' )
+ );
+
+ $dataValue->setContextPage(
+ $this->dataItemFactory->newDIWikiPage( 'Foo', SMW_NS_PROPERTY )
+ );
+
+ $dataValue->setOption( 'smwgDVFeatures', ~SMW_DV_PPLB );
+
+ $instance = new PropertySpecificationConstraintValueValidator();
+ $instance->validate( $dataValue );
+
+ $this->assertFalse(
+ $instance->hasConstraintViolation()
+ );
+
+ $this->assertNotEmpty(
+ $dataValue->getErrors()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/UniquenessConstraintValueValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/UniquenessConstraintValueValidatorTest.php
new file mode 100644
index 00000000..ba1c43ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DataValues/ValueValidators/UniquenessConstraintValueValidatorTest.php
@@ -0,0 +1,190 @@
+<?php
+
+namespace SMW\Tests\DataValues\ValueValidators;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ValueValidators\UniquenessConstraintValueValidator;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\DataValues\ValueValidators\UniquenessConstraintValueValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class UniquenessConstraintValueValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+ private $propertySpecificationLookup;
+ private $store;
+ private $entityValueUniquenessConstraintChecker;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->entityValueUniquenessConstraintChecker = $this->getMockBuilder( '\SMW\SQLStore\EntityValueUniquenessConstraintChecker' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'service' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'service' )
+ ->with( $this->equalTo( 'EntityValueUniquenessConstraintChecker' ) )
+ ->will( $this->returnValue( $this->entityValueUniquenessConstraintChecker ) );
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ UniquenessConstraintValueValidator::class,
+ new UniquenessConstraintValueValidator( $this->store, $this->propertySpecificationLookup )
+ );
+ }
+
+ public function testCanNotValidateOnNull() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getContextPage' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( null ) );
+
+ $dataValue->expects( $this->never() )
+ ->method( 'getProperty' );
+
+ $dataValue->expects( $this->never() )
+ ->method( 'getDataItem' );
+
+ $dataValue->setOption(
+ 'smwgDVFeatures',
+ SMW_DV_PVUC
+ );
+
+ $instance = new UniquenessConstraintValueValidator(
+ $this->store,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->validate( $dataValue );
+ }
+
+ public function testValidate_HasNoConstraintViolation() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'ValidAllowedValue' );
+
+ $this->entityValueUniquenessConstraintChecker->expects( $this->atLeastOnce() )
+ ->method( 'checkConstraint' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'hasUniquenessConstraint' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getContextPage' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIWikiPage( 'UV', NS_MAIN ) ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Foo' ) ) );
+
+ $dataValue->setOption(
+ 'smwgDVFeatures',
+ SMW_DV_PVUC
+ );
+
+ $instance = new UniquenessConstraintValueValidator(
+ $this->store,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->clear();
+ $instance->validate( $dataValue );
+
+ $this->assertFalse(
+ $instance->hasConstraintViolation()
+ );
+ }
+
+ public function testValidate_HasConstraintViolation() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'ValidAllowedValue_2' );
+
+ $this->entityValueUniquenessConstraintChecker->expects( $this->atLeastOnce() )
+ ->method( 'checkConstraint' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN ) ] ) );
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'hasUniquenessConstraint' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getProperty', 'getDataItem', 'getContextPage', 'addErrorMsg' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIWikiPage( 'UV', NS_MAIN ) ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $property ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'addErrorMsg' )
+ ->with( $this->equalTo( [ 'smw-datavalue-uniqueness-constraint-error', $property->getLabel(), '...', 'Foo' ] ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Foo' ) ) );
+
+ $dataValue->setOption(
+ 'smwgDVFeatures',
+ SMW_DV_PVUC
+ );
+
+ $instance = new UniquenessConstraintValueValidator(
+ $this->store,
+ $this->propertySpecificationLookup
+ );
+
+ $instance->validate( $dataValue );
+
+ $this->assertTrue(
+ $instance->hasConstraintViolation()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DefinesTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DefinesTest.php
new file mode 100644
index 00000000..1982c1af
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/DefinesTest.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DefinesTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider constantsDataProvider
+ */
+ public function testConstants( $constant, $expected ) {
+ $this->assertEquals( $expected, $constant );
+ }
+
+ public function constantsDataProvider() {
+ return [
+ [ SMW_HEADERS_SHOW, 2 ],
+ [ SMW_HEADERS_PLAIN, 1 ],
+ [ SMW_HEADERS_HIDE, 0 ],
+ [ SMW_OUTPUT_HTML, 1 ],
+ [ SMW_OUTPUT_WIKI, 2 ],
+ [ SMW_OUTPUT_FILE, 3 ],
+ [ SMW_FACTBOX_HIDDEN, 1 ],
+ [ SMW_FACTBOX_SPECIAL, 2 ],
+ [ SMW_FACTBOX_NONEMPTY, 3 ],
+ [ SMW_FACTBOX_SHOWN, 5 ],
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/DispatchingDescriptionDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/DispatchingDescriptionDeserializerTest.php
new file mode 100644
index 00000000..80c58774
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/DispatchingDescriptionDeserializerTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace SMW\Tests\Deserializers\DVDescriptionDeserializer;
+
+use SMW\Deserializers\DVDescriptionDeserializer\DispatchingDescriptionDeserializer;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Deserializers\DVDescriptionDeserializer\DispatchingDescriptionDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class DispatchingDescriptionDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\DispatchingDescriptionDeserializer',
+ new DispatchingDescriptionDeserializer()
+ );
+ }
+
+ public function testGetDescriptionDeserializerForMatchableDataValue() {
+
+ $descriptionDeserializer = $this->getMockBuilder( '\SMW\Deserializers\DVDescriptionDeserializer\DescriptionDeserializer' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $descriptionDeserializer->expects( $this->once() )
+ ->method( 'isDeserializerFor' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DispatchingDescriptionDeserializer();
+ $instance->addDescriptionDeserializer( $descriptionDeserializer );
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\DescriptionDeserializer',
+ $instance->getDescriptionDeserializerBy( $dataValue )
+ );
+ }
+
+ public function testGetDefaultDescriptionDeserializerForMatchableDataValue() {
+
+ $descriptionDeserializer = $this->getMockBuilder( '\SMW\Deserializers\DVDescriptionDeserializer\DescriptionDeserializer' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $descriptionDeserializer->expects( $this->once() )
+ ->method( 'isDeserializerFor' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DispatchingDescriptionDeserializer();
+ $instance->addDefaultDescriptionDeserializer( $descriptionDeserializer );
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\DescriptionDeserializer',
+ $instance->getDescriptionDeserializerBy( $dataValue )
+ );
+ }
+
+ public function testTryToGetDescriptionDeserializerForNonDispatchableDataValueThrowsException() {
+
+ $descriptionDeserializer = $this->getMockBuilder( '\SMW\Deserializers\DVDescriptionDeserializer\DescriptionDeserializer' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $descriptionDeserializer->expects( $this->once() )
+ ->method( 'isDeserializerFor' )
+ ->will( $this->returnValue( false ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DispatchingDescriptionDeserializer();
+ $instance->addDescriptionDeserializer( $descriptionDeserializer );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getDescriptionDeserializerBy( $dataValue );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/MonolingualTextValueDescriptionDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/MonolingualTextValueDescriptionDeserializerTest.php
new file mode 100644
index 00000000..3d3617f6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/MonolingualTextValueDescriptionDeserializerTest.php
@@ -0,0 +1,159 @@
+<?php
+
+namespace SMW\Tests\Deserializers\DVDescriptionDeserializer;
+
+use SMW\DataValueFactory;
+use SMW\DataValues\MonolingualTextValue;
+use SMW\Deserializers\DVDescriptionDeserializer\MonolingualTextValueDescriptionDeserializer;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Deserializers\DVDescriptionDeserializer\MonolingualTextValueDescriptionDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class MonolingualTextValueDescriptionDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\MonolingualTextValueDescriptionDeserializer',
+ new MonolingualTextValueDescriptionDeserializer()
+ );
+ }
+
+ public function testIsDeserializerForTimeValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMW\DataValues\MonolingualTextValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new MonolingualTextValueDescriptionDeserializer();
+
+ $this->assertTrue(
+ $instance->isDeserializerFor( $dataValue )
+ );
+ }
+
+ public function testNonStringThrowsException() {
+
+ $recordValue = $this->getMockBuilder( '\SMW\DataValues\MonolingualTextValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new MonolingualTextValueDescriptionDeserializer();
+ $instance->setDataValue( $recordValue );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->deserialize( [] );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testDeserialize( $value, $decription, $queryString, $dvFeatures ) {
+
+ $monolingualTextValue = DataValueFactory::getInStance()->newDataValueByType(
+ MonolingualTextValue::TYPE_ID
+ );
+
+ $monolingualTextValue->setOption( 'smwgDVFeatures', $dvFeatures );
+
+ $instance = new MonolingualTextValueDescriptionDeserializer();
+ $instance->setDataValue( $monolingualTextValue );
+
+ $this->assertInstanceOf(
+ $decription,
+ $instance->deserialize( $value )
+ );
+
+ $this->assertEquals(
+ $queryString,
+ $instance->deserialize( $value )->getQueryString()
+ );
+ }
+
+ public function valueProvider() {
+
+ #0
+ $provider[] = [
+ 'Jan;1970',
+ '\SMW\Query\Language\Conjunction',
+ '[[Text::Jan;1970]] [[Language code::+]]',
+ SMW_DV_MLTV_LCODE
+ ];
+
+ #1
+ $provider[] = [
+ 'Jan;1970',
+ '\SMW\Query\Language\SomeProperty',
+ '[[Text::Jan;1970]]',
+ SMW_DV_NONE
+ ];
+
+ #2
+ $provider[] = [
+ 'Jan@en',
+ '\SMW\Query\Language\Conjunction',
+ '[[Text::Jan]] [[Language code::en]]',
+ SMW_DV_MLTV_LCODE
+ ];
+
+ #3
+ $provider[] = [
+ '@en',
+ '\SMW\Query\Language\Conjunction',
+ '[[Text::+]] [[Language code::en]]',
+ SMW_DV_MLTV_LCODE
+ ];
+
+ #4
+ $provider[] = [
+ '@EN',
+ '\SMW\Query\Language\Conjunction',
+ '[[Text::+]] [[Language code::en]]',
+ SMW_DV_MLTV_LCODE
+ ];
+
+ #5
+ $provider[] = [
+ '@~zh*',
+ '\SMW\Query\Language\Conjunction',
+ '[[Text::+]] [[Language code::~zh*]]',
+ SMW_DV_MLTV_LCODE
+ ];
+
+ #6
+ $provider[] = [
+ '?',
+ '\SMW\Query\Language\Conjunction',
+ '[[Text::+]] [[Language code::+]]',
+ SMW_DV_MLTV_LCODE
+ ];
+
+ #7
+ $provider[] = [
+ '?',
+ '\SMW\Query\Language\SomeProperty',
+ '[[Text::+]]',
+ SMW_DV_NONE
+ ];
+
+ #8
+ $provider[] = [
+ '',
+ '\SMW\Query\Language\ThingDescription',
+ '',
+ SMW_DV_MLTV_LCODE
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/NumberValueDescriptionDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/NumberValueDescriptionDeserializerTest.php
new file mode 100644
index 00000000..e40e2d1a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/NumberValueDescriptionDeserializerTest.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace SMW\Tests\Deserializers\DVDescriptionDeserializer;
+
+use SMW\Deserializers\DVDescriptionDeserializer\NumberValueDescriptionDeserializer;
+
+/**
+ * @covers \SMW\Deserializers\DVDescriptionDeserializer\NumberValueDescriptionDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class NumberValueDescriptionDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ NumberValueDescriptionDeserializer::class,
+ new NumberValueDescriptionDeserializer()
+ );
+ }
+
+ public function testIsDeserializerForNumberValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new NumberValueDescriptionDeserializer();
+
+ $this->assertTrue(
+ $instance->isDeserializerFor( $dataValue )
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testDeserialize( $value, $decription ) {
+
+ $numberValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $numberValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $numberValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( new \SMWDINumber( 42 ) ) );
+
+ $numberValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( new \SMW\DIProperty( 'Foo' ) ) );
+
+ $instance = new NumberValueDescriptionDeserializer();
+ $instance->setDataValue( $numberValue );
+
+ $this->assertInstanceOf(
+ $decription,
+ $instance->deserialize( $value )
+ );
+ }
+
+ public function testInvalidNumberValueReturnsThingDescription() {
+
+ $numberValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $numberValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new NumberValueDescriptionDeserializer();
+ $instance->setDataValue( $numberValue );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Language\ThingDescription',
+ $instance->deserialize( 'Foo' )
+ );
+ }
+
+ public function valueProvider() {
+
+ $provider[] = [
+ '42',
+ '\SMW\Query\Language\ValueDescription'
+ ];
+
+ $provider[] = [
+ '~42',
+ '\SMW\Query\Language\Conjunction'
+ ];
+
+ $provider[] = [
+ '~*42*',
+ '\SMW\Query\Language\Conjunction'
+ ];
+
+ $provider[] = [
+ '~-42',
+ '\SMW\Query\Language\Conjunction'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/RecordValueDescriptionDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/RecordValueDescriptionDeserializerTest.php
new file mode 100644
index 00000000..6589fb59
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/RecordValueDescriptionDeserializerTest.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace SMW\Tests\Deserializers\DVDescriptionDeserializer;
+
+use SMW\Deserializers\DVDescriptionDeserializer\RecordValueDescriptionDeserializer;
+use SMW\DIProperty;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Deserializers\DVDescriptionDeserializer\RecordValueDescriptionDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class RecordValueDescriptionDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\RecordValueDescriptionDeserializer',
+ new RecordValueDescriptionDeserializer()
+ );
+ }
+
+ public function testIsDeserializerForTimeValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMWRecordValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new RecordValueDescriptionDeserializer();
+
+ $this->assertTrue(
+ $instance->isDeserializerFor( $dataValue )
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testDeserialize( $value, $propertyDataItems, $decription ) {
+
+ $recordValue = $this->getMockBuilder( '\SMWRecordValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $recordValue->expects( $this->any() )
+ ->method( 'getValuesFromString' )
+ ->with( $this->stringContains( $value ) )
+ ->will( $this->returnCallback( function( $value ) {
+ return explode(';', $value );
+ } ) );
+
+ $recordValue->expects( $this->any() )
+ ->method( 'getPropertyDataItems' )
+ ->will( $this->returnValue( $propertyDataItems ) );
+
+ $instance = new RecordValueDescriptionDeserializer();
+ $instance->setDataValue( $recordValue );
+
+ $this->assertInstanceOf(
+ $decription,
+ $instance->deserialize( $value )
+ );
+ }
+
+ public function testInvalidRecordValueReturnsThingDescription() {
+
+ $recordValue = $this->getMockBuilder( '\SMWRecordValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $recordValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( false ) );
+
+ $recordValue->expects( $this->any() )
+ ->method( 'getPropertyDataItems' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new RecordValueDescriptionDeserializer();
+ $instance->setDataValue( $recordValue );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Language\ThingDescription',
+ $instance->deserialize( 'Foo' )
+ );
+ }
+
+ public function testNonStringThrowsException() {
+
+ $recordValue = $this->getMockBuilder( '\SMWRecordValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new RecordValueDescriptionDeserializer();
+ $instance->setDataValue( $recordValue );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->deserialize( [] );
+ }
+
+ public function valueProvider() {
+
+ $provider[] = [
+ 'Jan;1970',
+ [ new DIProperty( 'Foo' ) ],
+ '\SMW\Query\Language\SomeProperty'
+ ];
+
+ $provider[] = [
+ 'Jan;1970',
+ [ new DIProperty( 'Foo' ), new DIProperty( 'Bar' ) ],
+ '\SMW\Query\Language\Conjunction'
+ ];
+
+ $provider[] = [
+ '?',
+ [ new DIProperty( 'Foo' ), new DIProperty( 'Bar' ) ],
+ '\SMW\Query\Language\ThingDescription'
+ ];
+
+ $provider[] = [
+ '',
+ [],
+ '\SMW\Query\Language\ThingDescription'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/SomeValueDescriptionDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/SomeValueDescriptionDeserializerTest.php
new file mode 100644
index 00000000..9b1820a7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/SomeValueDescriptionDeserializerTest.php
@@ -0,0 +1,201 @@
+<?php
+
+namespace SMW\Tests\Deserializers\DVDescriptionDeserializer;
+
+use SMW\ApplicationFactory;
+use SMW\Deserializers\DVDescriptionDeserializer\SomeValueDescriptionDeserializer;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Deserializers\DVDescriptionDeserializer\SomeValueDescriptionDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class SomeValueDescriptionDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataItemFactory = ApplicationFactory::getInstance()->getDataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\SomeValueDescriptionDeserializer',
+ new SomeValueDescriptionDeserializer()
+ );
+ }
+
+ public function testIsDeserializerForDataValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new SomeValueDescriptionDeserializer();
+
+ $this->assertTrue(
+ $instance->isDeserializerFor( $dataValue )
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testDeserialize( $value, $decription ) {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid', 'getDataItem', 'getProperty', 'setUserValue' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->once() )
+ ->method( 'setUserValue' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( false ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue($this->dataItemFactory->newDITime( 1, '1970' ) ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Foo' ) ) );
+
+ $instance = new SomeValueDescriptionDeserializer();
+ $instance->setDataValue( $dataValue );
+
+ $this->assertInstanceOf(
+ $decription,
+ $instance->deserialize( $value )
+ );
+ }
+
+ /**
+ * @dataProvider likeNotLikeProvider
+ */
+ public function testDeserializeForLikeNotLike( $value ) {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'setUserValue' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->once() )
+ ->method( 'setUserValue' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( false ) );
+
+ $instance = new SomeValueDescriptionDeserializer();
+ $instance->setDataValue( $dataValue );
+
+ $instance->deserialize( $value );
+ }
+
+ public function testInvalidDataValueRetunsThingDescription() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new SomeValueDescriptionDeserializer();
+ $instance->setDataValue( $dataValue );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Language\ThingDescription',
+ $instance->deserialize( 'Foo' )
+ );
+ }
+
+ public function testNonStringThrowsException() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new SomeValueDescriptionDeserializer();
+ $instance->setDataValue( $dataValue );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->deserialize( [] );
+ }
+
+ public function testWikiPageValueOnNonMainNamespace() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid', 'getDataItem', 'getProperty', 'setUserValue' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'setUserValue' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( false ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIWikiPage( '~Foo', NS_HELP ) ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Foo' ) ) );
+
+ $instance = new SomeValueDescriptionDeserializer();
+ $instance->setDataValue( $dataValue );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Language\Conjunction',
+ $instance->deserialize( 'Help:~Foo' )
+ );
+ }
+
+ public function valueProvider() {
+
+ $provider[] = [
+ 'Foo',
+ '\SMW\Query\Language\ValueDescription'
+ ];
+
+ return $provider;
+ }
+
+
+ public function likeNotLikeProvider() {
+
+ $provider[] = [
+ '~Foo'
+ ];
+
+ $provider[] = [
+ '!~Foo'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/TimeValueDescriptionDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/TimeValueDescriptionDeserializerTest.php
new file mode 100644
index 00000000..12e80092
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializer/TimeValueDescriptionDeserializerTest.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace SMW\Tests\Deserializers\DVDescriptionDeserializer;
+
+use SMW\Deserializers\DVDescriptionDeserializer\TimeValueDescriptionDeserializer;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Deserializers\DVDescriptionDeserializer\TimeValueDescriptionDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class TimeValueDescriptionDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\TimeValueDescriptionDeserializer',
+ new TimeValueDescriptionDeserializer()
+ );
+ }
+
+ public function testIsDeserializerForTimeValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMWTimeValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new TimeValueDescriptionDeserializer();
+
+ $this->assertTrue(
+ $instance->isDeserializerFor( $dataValue )
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testDeserialize( $value, $decription ) {
+
+ $timeValue = $this->getMockBuilder( '\SMWTimeValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $timeValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $timeValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( new \SMWDITime( 1, '1970' ) ) );
+
+ $timeValue->expects( $this->any() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( new \SMW\DIProperty( 'Foo' ) ) );
+
+ $instance = new TimeValueDescriptionDeserializer();
+ $instance->setDataValue( $timeValue );
+
+ $this->assertInstanceOf(
+ $decription,
+ $instance->deserialize( $value )
+ );
+ }
+
+ public function testInvalidTimeValueReturnsThingDescription() {
+
+ $timeValue = $this->getMockBuilder( '\SMWTimeValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $timeValue->expects( $this->any() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new TimeValueDescriptionDeserializer();
+ $instance->setDataValue( $timeValue );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Language\ThingDescription',
+ $instance->deserialize( 'Foo' )
+ );
+ }
+
+ public function testNonStringThrowsException() {
+
+ $timeValue = $this->getMockBuilder( '\SMWTimeValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new TimeValueDescriptionDeserializer();
+ $instance->setDataValue( $timeValue );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->deserialize( [] );
+ }
+
+ public function valueProvider() {
+
+ $provider[] = [
+ 'Jan 1970',
+ '\SMW\Query\Language\ValueDescription'
+ ];
+
+ $provider[] = [
+ '~Jan 1970',
+ '\SMW\Query\Language\Conjunction'
+ ];
+
+ $provider[] = [
+ '!~Jan 1970',
+ '\SMW\Query\Language\Disjunction'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializerRegistryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializerRegistryTest.php
new file mode 100644
index 00000000..226402d4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/DVDescriptionDeserializerRegistryTest.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace SMW\Tests\Deserializers;
+
+use SMW\Deserializers\DVDescriptionDeserializerRegistry;
+
+/**
+ * @covers \SMW\Deserializers\DVDescriptionDeserializerRegistry
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class DVDescriptionDeserializerRegistryTest extends \PHPUnit_Framework_TestCase {
+
+ protected function tearDown() {
+ DVDescriptionDeserializerRegistry::getInstance()->clear();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $dispatchingDescriptionDeserializer = $this->getMockBuilder( '\SMW\Deserializers\DVDescriptionDeserializer\DispatchingDescriptionDeserializer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializerRegistry',
+ new DVDescriptionDeserializerRegistry( $dispatchingDescriptionDeserializer )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializerRegistry',
+ DVDescriptionDeserializerRegistry::getInstance()
+ );
+ }
+
+ public function testCanConstructSomeValueDescriptionDeserializer() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DVDescriptionDeserializerRegistry();
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\SomeValueDescriptionDeserializer',
+ $instance->getDescriptionDeserializerBy( $dataValue )
+ );
+ }
+
+ public function testCanConstructTimeValueDescriptionDeserializer() {
+
+ $dataValue = $this->getMockBuilder( '\SMWTimeValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DVDescriptionDeserializerRegistry();
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\TimeValueDescriptionDeserializer',
+ $instance->getDescriptionDeserializerBy( $dataValue )
+ );
+ }
+
+ public function testCanConstructNumberValueDescriptionDeserializer() {
+
+ $dataValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DVDescriptionDeserializerRegistry();
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\NumberValueDescriptionDeserializer',
+ $instance->getDescriptionDeserializerBy( $dataValue )
+ );
+ }
+
+ public function testCanConstructRecordValueDescriptionDeserializer() {
+
+ $dataValue = $this->getMockBuilder( '\SMWRecordValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DVDescriptionDeserializerRegistry();
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\RecordValueDescriptionDeserializer',
+ $instance->getDescriptionDeserializerBy( $dataValue )
+ );
+ }
+
+ public function testRegisterAdditionalDescriptionDeserializer() {
+
+ $descriptionDeserializer = $this->getMockBuilder( '\SMW\Deserializers\DVDescriptionDeserializer\DescriptionDeserializer' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $descriptionDeserializer->expects( $this->once() )
+ ->method( 'isDeserializerFor' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DVDescriptionDeserializerRegistry();
+ $instance->registerDescriptionDeserializer( $descriptionDeserializer );
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\DVDescriptionDeserializer\DescriptionDeserializer',
+ $instance->getDescriptionDeserializerBy( $dataValue )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/ExpDataDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/ExpDataDeserializerTest.php
new file mode 100644
index 00000000..4dba4fdb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/ExpDataDeserializerTest.php
@@ -0,0 +1,163 @@
+<?php
+
+namespace SMW\Tests\Deserializers;
+
+use SMW\Deserializers\ExpDataDeserializer;
+use SMW\Exporter\Element\ExpLiteral;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Serializers\ExpDataSerializer;
+use SMWDIBlob as DIBlob;
+use SMWExpData as ExpData;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Deserializers\ExpDataDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpDataDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstructor() {
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\ExpDataDeserializer',
+ new ExpDataDeserializer()
+ );
+ }
+
+ public function testInvalidSerializerObjectThrowsException() {
+
+ $instance = new ExpDataDeserializer();
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+ $instance->deserialize( 'Foo' );
+ }
+
+ public function testVersionMismatchThrowsException() {
+
+ $instance = new ExpDataDeserializer();
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+ $instance->deserialize( [ 'version' => 0.2 ] );
+ }
+
+ /**
+ * @dataProvider expDataProvider
+ */
+ public function testDeserialize( $seralization, $expected ) {
+
+ $instance = new ExpDataDeserializer();
+
+ $this->assertEquals(
+ $expected,
+ $instance->deserialize( $seralization )
+ );
+ }
+
+ /**
+ * @dataProvider expDataProvider
+ */
+ public function testDeserializeToCompareHash( $seralization, $expected ) {
+
+ $instance = new ExpDataDeserializer();
+
+ $this->assertEquals(
+ $expected->getHash(),
+ $instance->deserialize( $seralization )->getHash()
+ );
+ }
+
+ public function expDataProvider() {
+
+ $serializier = new ExpDataSerializer();
+
+ #0
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $provider[] = [
+ $serializier->serialize( $expData ),
+ $expData
+ ];
+
+ #1
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $provider[] = [
+ $serializier->serialize( $expData ),
+ $expData
+ ];
+
+ #2 Nested
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', new DIBlob( 'SomeText' ) ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpData( new ExpNsResource( 'Foo', 'Bar', 'Mo', new DIBlob( 'SomeOtherText' ) ) )
+ );
+
+ $provider[] = [
+ $serializier->serialize( $expData ),
+ $expData
+ ];
+
+ #2 Nested level 2+3
+
+ $expDataLevel2 = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', new DIBlob( 'SomeOtherText' ) )
+ );
+
+ $expDataLevel2->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', new DIBlob( 'SomeText' ) ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $expDataLevel2->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpData( new ExpNsResource( 'Foo', 'Bar', 'Mo', null ) ) // 3
+ );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', new DIBlob( 'SomeText' ) ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ $expDataLevel2
+ );
+
+ $provider[] = [
+ $serializier->serialize( $expData ),
+ $expData
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/SemanticDataDeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/SemanticDataDeserializerTest.php
new file mode 100644
index 00000000..b9c0dcda
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Deserializers/SemanticDataDeserializerTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace SMW\Tests\Deserializers;
+
+use SMW\Deserializers\SemanticDataDeserializer;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Deserializers\SemanticDataDeserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SemanticDataDeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstructor() {
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\SemanticDataDeserializer',
+ new SemanticDataDeserializer()
+ );
+ }
+
+ public function testDeserializerInvalidVersionThrowsException() {
+
+ $instance = new SemanticDataDeserializer();
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+
+ $instance->deserialize(
+ [ 'version' => 'Foo' ]
+ );
+ }
+
+ public function testDeserializerForInvalidSubjectThrowsException() {
+
+ $instance = new SemanticDataDeserializer();
+
+ $this->setExpectedException( '\SMW\Exception\DataItemDeserializationException' );
+
+ $instance->deserialize(
+ [ 'subject' => '--#Foo' ]
+ );
+ }
+
+ public function testDeserializerForMissingSubjectThrowsException() {
+
+ $instance = new SemanticDataDeserializer();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->deserialize( [] );
+ }
+
+ public function testDeserializerForEmptyData() {
+
+ $instance = new SemanticDataDeserializer();
+
+ $this->assertInstanceOf(
+ 'SMW\SemanticData',
+ $instance->deserialize( [ 'subject' => 'Foo#0##' ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/ElasticClientTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/ElasticClientTaskHandlerTest.php
new file mode 100644
index 00000000..833638b8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/ElasticClientTaskHandlerTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace SMW\Tests\Elastic\Admin;
+
+use SMW\Elastic\Admin\ElasticClientTaskHandler;
+use SMW\Elastic\Connection\DummyClient;
+
+/**
+ * @covers \SMW\Elastic\Admin\ElasticClientTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ElasticClientTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $outputFormatter;
+ private $webRequest;
+ private $store;
+
+ protected function setUp() {
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( new DummyClient() ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ElasticClientTaskHandler::class,
+ new ElasticClientTaskHandler( $this->outputFormatter )
+ );
+ }
+
+ public function testIsTask() {
+
+ $task = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\TaskHandler' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getTask' ] )
+ ->getMockForAbstractClass();
+
+ $task->expects( $this->once() )
+ ->method( 'getTask' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new ElasticClientTaskHandler(
+ $this->outputFormatter,
+ [
+ $task
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->isTaskFor( 'Foo' )
+ );
+ }
+
+ public function testGetHtml_OnNoAvailableNodes() {
+
+ $this->outputFormatter->expects( $this->never() )
+ ->method( 'createSpecialPageLink' );
+
+ $instance = new ElasticClientTaskHandler(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $this->store );
+
+ $this->assertEmpty(
+ $instance->getHtml()
+ );
+ }
+
+ public function testGetHtml_OnAvailableNodes() {
+
+ $this->outputFormatter->expects( $this->once() )
+ ->method( 'createSpecialPageLink' );
+
+ $client = $this->getMockBuilder( '\SMW\Elastic\Connection\DummyClient' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $client->expects( $this->any() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $client ) );
+
+ $instance = new ElasticClientTaskHandler(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $store );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHandleRequest_OnNoAvailableNodes() {
+
+ $this->outputFormatter->expects( $this->once() )
+ ->method( 'addParentLink' )
+ ->with( $this->equalTo( [ 'tab' => 'supplement' ] ) );
+
+ $instance = new ElasticClientTaskHandler(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $this->store );
+ $instance->handleRequest( $this->webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/IndicesInfoProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/IndicesInfoProviderTest.php
new file mode 100644
index 00000000..6b49f410
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/IndicesInfoProviderTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\Elastic\Admin;
+
+use SMW\Elastic\Admin\IndicesInfoProvider;
+use SMW\Elastic\Connection\DummyClient;
+
+/**
+ * @covers \SMW\Elastic\Admin\IndicesInfoProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class IndicesInfoProviderTest extends \PHPUnit_Framework_TestCase {
+
+ private $outputFormatter;
+ private $webRequest;
+ private $store;
+
+ protected function setUp() {
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( new DummyClient() ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ IndicesInfoProvider::class,
+ new IndicesInfoProvider( $this->outputFormatter )
+ );
+ }
+
+ public function testGetTask() {
+
+ $instance = new IndicesInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertEquals(
+ 'indices',
+ $instance->getSupplementTask()
+ );
+
+ $this->assertEquals(
+ 'elastic/indices',
+ $instance->getTask()
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new IndicesInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $this->outputFormatter->expects( $this->once() )
+ ->method( 'addParentLink' )
+ ->with( $this->equalTo( [ 'action' => 'elastic' ] ) );
+
+ $instance = new IndicesInfoProvider(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $this->store );
+ $instance->handleRequest( $this->webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/MappingsInfoProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/MappingsInfoProviderTest.php
new file mode 100644
index 00000000..b5bb8669
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/MappingsInfoProviderTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\Elastic\Admin;
+
+use SMW\Elastic\Admin\MappingsInfoProvider;
+use SMW\Elastic\Connection\DummyClient;
+
+/**
+ * @covers \SMW\Elastic\Admin\MappingsInfoProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class MappingsInfoProviderTest extends \PHPUnit_Framework_TestCase {
+
+ private $outputFormatter;
+ private $webRequest;
+ private $store;
+
+ protected function setUp() {
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( new DummyClient() ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ MappingsInfoProvider::class,
+ new MappingsInfoProvider( $this->outputFormatter )
+ );
+ }
+
+ public function testGetTask() {
+
+ $instance = new MappingsInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertEquals(
+ 'mappings',
+ $instance->getSupplementTask()
+ );
+
+ $this->assertEquals(
+ 'elastic/mappings',
+ $instance->getTask()
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new MappingsInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $this->outputFormatter->expects( $this->once() )
+ ->method( 'addParentLink' )
+ ->with( $this->equalTo( [ 'action' => 'elastic' ] ) );
+
+ $instance = new MappingsInfoProvider(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $this->store );
+ $instance->handleRequest( $this->webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/NodesInfoProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/NodesInfoProviderTest.php
new file mode 100644
index 00000000..00c54674
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/NodesInfoProviderTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\Elastic\Admin;
+
+use SMW\Elastic\Admin\NodesInfoProvider;
+use SMW\Elastic\Connection\DummyClient;
+
+/**
+ * @covers \SMW\Elastic\Admin\NodesInfoProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class NodesInfoProviderTest extends \PHPUnit_Framework_TestCase {
+
+ private $outputFormatter;
+ private $webRequest;
+ private $store;
+
+ protected function setUp() {
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( new DummyClient() ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ NodesInfoProvider::class,
+ new NodesInfoProvider( $this->outputFormatter )
+ );
+ }
+
+ public function testGetTask() {
+
+ $instance = new NodesInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertEquals(
+ 'nodes',
+ $instance->getSupplementTask()
+ );
+
+ $this->assertEquals(
+ 'elastic/nodes',
+ $instance->getTask()
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new NodesInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $this->outputFormatter->expects( $this->once() )
+ ->method( 'addParentLink' )
+ ->with( $this->equalTo( [ 'action' => 'elastic' ] ) );
+
+ $instance = new NodesInfoProvider(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $this->store );
+ $instance->handleRequest( $this->webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/SettingsInfoProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/SettingsInfoProviderTest.php
new file mode 100644
index 00000000..ea2f6fb1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Admin/SettingsInfoProviderTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\Elastic\Admin;
+
+use SMW\Elastic\Admin\SettingsInfoProvider;
+use SMW\Elastic\Connection\DummyClient;
+
+/**
+ * @covers \SMW\Elastic\Admin\SettingsInfoProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SettingsInfoProviderTest extends \PHPUnit_Framework_TestCase {
+
+ private $outputFormatter;
+ private $webRequest;
+ private $store;
+
+ protected function setUp() {
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( new DummyClient() ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SettingsInfoProvider::class,
+ new SettingsInfoProvider( $this->outputFormatter )
+ );
+ }
+
+ public function testGetTask() {
+
+ $instance = new SettingsInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertEquals(
+ 'settings',
+ $instance->getSupplementTask()
+ );
+
+ $this->assertEquals(
+ 'elastic/settings',
+ $instance->getTask()
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new SettingsInfoProvider(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $this->outputFormatter->expects( $this->once() )
+ ->method( 'addParentLink' )
+ ->with( $this->equalTo( [ 'action' => 'elastic' ] ) );
+
+ $instance = new SettingsInfoProvider(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $this->store );
+ $instance->handleRequest( $this->webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ConfigTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ConfigTest.php
new file mode 100644
index 00000000..e44945a9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ConfigTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace SMW\Tests\Elastic;
+
+use SMW\Elastic\Config;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\Config
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ConfigTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Config::class,
+ new Config()
+ );
+ }
+
+ public function testLoadFromJSON() {
+
+ $instance = new Config();
+ $instance->set( 'Foo', '123' );
+ $instance->set( 'Bar', '456' );
+
+ $instance->loadFromJSON( json_encode( [ 'Foo' => 456 ] ) );
+
+ $this->assertEquals(
+ 456,
+ $instance->dotGet( 'Foo' )
+ );
+
+ $this->assertEquals(
+ '456',
+ $instance->dotGet( 'Bar' )
+ );
+
+ $instance->set( 'A', [ 'B' => [ 'C', 'D' ] ] );
+
+ $this->assertEquals(
+ [ 'C', 'D' ],
+ $instance->dotGet( 'A.B' )
+ );
+
+ $instance->loadFromJSON( json_encode( [ 'A.B' => 'C' ] ) );
+
+ $this->assertEquals(
+ [ 'C', 'D' ],
+ $instance->dotGet( 'A.B' )
+ );
+
+ $instance->loadFromJSON( json_encode( [ 'A' => [ 'B' => [ 'E' ] ] ] ) );
+
+ $this->assertEquals(
+ [ 'E' ],
+ $instance->dotGet( 'A.B' )
+ );
+
+ $instance->loadFromJSON( json_encode( [ 'A' => [ 'B' => 'C' ] ] ) );
+
+ $this->assertEquals(
+ 'C',
+ $instance->dotGet( 'A.B' )
+ );
+ }
+
+ public function testReadfile_InaccessibleFileThrowsException() {
+
+ $instance = new Config();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->readFile( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ClientTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ClientTest.php
new file mode 100644
index 00000000..a5a81a32
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ClientTest.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace SMW\Tests\Elastic\Connection;
+
+use SMW\Elastic\Connection\Client;
+use SMW\Options;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\Connection\Client
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ClientTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $elasticClient;
+ private $cache;
+
+ protected function setUp() {
+
+ if ( !class_exists( '\Elasticsearch\Client' ) ) {
+ $this->markTestSkipped( "elasticsearch-php dependency is not available." );
+ }
+
+ $this->elasticClient = $this->getMockBuilder( '\Elasticsearch\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Client::class,
+ new Client( $this->elasticClient )
+ );
+ }
+
+ public function testBulkOnIllegalArgumentErrorThrowsReplicationException() {
+
+ $options = new Options (
+ [
+ 'replication' => [
+ 'throw.exception.on.illegal.argument.error' => true
+ ]
+ ]
+ );
+
+ $response = '{"took":67,"errors":true,"items":[{"index":{"_index":"smw-data-test","_type":"data","_id":"14099","status":400,"error":{"type":"illegal_argument_exception","reason":"Limit of total fields [20] in index [smw-data-test] has been exceeded"}}}]}';
+
+ $this->elasticClient->expects( $this->once() )
+ ->method( 'bulk' )
+ ->will( $this->returnValue( json_decode( $response, true ) ) );
+
+ $instance = new Client(
+ $this->elasticClient,
+ $this->cache,
+ $options
+ );
+
+ $params = [
+ 'index' => 'foo'
+ ];
+
+ $this->setExpectedException( '\SMW\Elastic\Exception\ReplicationException' );
+ $instance->bulk( $params );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ConnectionProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ConnectionProviderTest.php
new file mode 100644
index 00000000..e446aeba
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Connection/ConnectionProviderTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace SMW\Tests\Elastic\Connection;
+
+use SMW\Elastic\Connection\ConnectionProvider;
+use SMW\Elastic\Connection\DummyClient;
+use SMW\Elastic\Connection\Client;
+use SMW\Options;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\Connection\ConnectionProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ConnectionProviderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $logger;
+ private $cache;
+
+ protected function setUp() {
+
+ $this->logger = $this->getMockBuilder( '\Psr\Log\LoggerInterface' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->options = new Options();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConnectionProvider::class,
+ new ConnectionProvider( $this->options, $this->cache )
+ );
+ }
+
+ public function testGetConnection_DummyClient() {
+
+ $options = new Options (
+ [
+ 'is.elasticstore' => false,
+ 'endpoints' => []
+ ]
+ );
+
+ $instance = new ConnectionProvider(
+ $options,
+ $this->cache
+ );
+
+ $instance->setLogger( $this->logger );
+
+ $this->assertInstanceOf(
+ DummyClient::class,
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetConnection_Client() {
+
+ if ( !class_exists( '\Elasticsearch\ClientBuilder' ) ) {
+ $this->markTestSkipped( "elasticsearch-php dependency is not available." );
+ }
+
+ $options = new Options (
+ [
+ 'is.elasticstore' => true,
+ 'endpoints' => []
+ ]
+ );
+
+ $instance = new ConnectionProvider(
+ $options,
+ $this->cache
+ );
+
+ $instance->setLogger( $this->logger );
+
+ $this->assertInstanceOf(
+ Client::class,
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetConnectionThrowsExceptionWhenNotInstalled() {
+
+ if ( class_exists( '\Elasticsearch\ClientBuilder' ) ) {
+ $this->markTestSkipped( "No exception thrown when ClientBuilder is available!" );
+ }
+
+ $options = new Options (
+ [
+ 'is.elasticstore' => true,
+ 'endpoints' => []
+ ]
+ );
+
+ $instance = new ConnectionProvider(
+ $options,
+ $this->cache
+ );
+
+ $this->setExpectedException( '\SMW\Elastic\Exception\ClientBuilderNotFoundException' );
+ $instance->getConnection();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ElasticFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ElasticFactoryTest.php
new file mode 100644
index 00000000..687b5c01
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/ElasticFactoryTest.php
@@ -0,0 +1,244 @@
+<?php
+
+namespace SMW\Tests\Elastic;
+
+use SMW\Elastic\ElasticFactory;
+
+/**
+ * @covers \SMW\Elastic\ElasticFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ElasticFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $outputFormatter;
+ private $conditionBuilder;
+ private $connection;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->conditionBuilder = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection = $this->getMockBuilder( '\SMW\Elastic\Connection\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ElasticFactory::class,
+ new ElasticFactory()
+ );
+ }
+
+ public function testCanConstructConfig() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Config',
+ $instance->newConfig()
+ );
+ }
+
+ public function testCanConstructConnectionProvider() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Connection\ConnectionProvider',
+ $instance->newConnectionProvider()
+ );
+ }
+
+ public function testCanConstructIndexer() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Indexer\Indexer',
+ $instance->newIndexer( $this->store )
+ );
+ }
+
+ public function testCanConstructFileIndexer() {
+
+ $indexer = $this->getMockBuilder( '\SMW\Elastic\Indexer\Indexer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Indexer\FileIndexer',
+ $instance->newFileIndexer( $indexer )
+ );
+ }
+
+ public function testCanConstructRollover() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Indexer\Rollover',
+ $instance->newRollover( $this->connection )
+ );
+ }
+
+ public function testCanConstructBulk() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Indexer\Bulk',
+ $instance->newBulk( $this->connection )
+ );
+ }
+
+ public function testCanConstructQueryEngine() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\QueryEngine',
+ $instance->newQueryEngine( $this->store )
+ );
+ }
+
+ public function testCanConstructRebuilder() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Indexer\Rebuilder',
+ $instance->newRebuilder( $this->store )
+ );
+ }
+
+ public function testCanConstructInfoTaskHandler() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\Admin\ElasticClientTaskHandler',
+ $instance->newInfoTaskHandler( $this->store, $this->outputFormatter )
+ );
+ }
+
+ public function testCanConstructConceptDescriptionInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter',
+ $instance->newConceptDescriptionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testCanConstructSomePropertyInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\SomePropertyInterpreter',
+ $instance->newSomePropertyInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testCanConstructSomeValueInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\SomeValueInterpreter',
+ $instance->newSomeValueInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testCanConstructClassDescriptionInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter',
+ $instance->newClassDescriptionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testCanConstructNamespaceDescriptionInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter',
+ $instance->newNamespaceDescriptionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testCanConstructValueDescriptionInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter',
+ $instance->newValueDescriptionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testCanConstructConjunctionInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\ConjunctionInterpreter',
+ $instance->newConjunctionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testCanConstructDisjunctionInterpreter() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Elastic\QueryEngine\DescriptionInterpreters\DisjunctionInterpreter',
+ $instance->newDisjunctionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testOnEntityReferenceCleanUpComplete() {
+
+ $instance = new ElasticFactory();
+
+ $this->assertTrue(
+ $instance->onEntityReferenceCleanUpComplete( $this->store, 42, null, false )
+ );
+ }
+
+ public function testOnTaskHandlerFactory() {
+
+ $instance = new ElasticFactory();
+ $taskHandlers = [];
+ $outputFormatter = null;
+
+ $this->assertTrue(
+ $instance->onTaskHandlerFactory( $taskHandlers, $this->store, $outputFormatter, null )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Exception/ClientBuilderNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Exception/ClientBuilderNotFoundExceptionTest.php
new file mode 100644
index 00000000..6cb6b234
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Exception/ClientBuilderNotFoundExceptionTest.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace SMW\Tests\Elastic\Exception;
+
+use SMW\Elastic\Exception\ClientBuilderNotFoundException;
+use RuntimeException;
+
+/**
+ * @covers \SMW\Elastic\Exception\ClientBuilderNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ClientBuilderNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ RuntimeException::class,
+ new ClientBuilderNotFoundException()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/FileIndexerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/FileIndexerTest.php
new file mode 100644
index 00000000..cf891053
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/FileIndexerTest.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace SMW\Tests\Elastic\Indexer;
+
+use SMW\Elastic\Indexer\FileIndexer;
+use SMW\DIWikiPage;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\Indexer\FileIndexer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FileIndexerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $indexer;
+ private $logger;
+
+ protected function setUp() {
+
+ $this->indexer = $this->getMockBuilder( '\SMW\Elastic\Indexer\Indexer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->logger = $this->getMockBuilder( '\Psr\Log\NullLogger' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FileIndexer::class,
+ new FileIndexer( $this->indexer )
+ );
+ }
+
+ public function testIndex() {
+
+ $file = $this->getMockBuilder( '\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $file->expects( $this->once() )
+ ->method( 'getFullURL' )
+ ->will( $this->returnValue( 'http://example.org/Foo.txt' ) );
+
+ $ingest = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'putPipeline' ] )
+ ->getMock();
+
+ $ingest->expects( $this->once() )
+ ->method( 'putPipeline' );
+
+ $client = $this->getMockBuilder( '\SMW\Elastic\Connection\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $client->expects( $this->once() )
+ ->method( 'ingest' )
+ ->will( $this->returnValue( $ingest ) );
+
+ $this->indexer->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $client ) );
+
+ $instance = new FileIndexer(
+ $this->indexer
+ );
+
+ $instance->setLogger( $this->logger );
+
+ $dataItem = DIWikiPage::newFromText( __METHOD__, NS_FILE );
+ $dataItem->setId( 42 );
+
+ $instance->index( $dataItem, $file );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerRecoveryJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerRecoveryJobTest.php
new file mode 100644
index 00000000..1789a97f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerRecoveryJobTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace SMW\Tests\Elastic\Indexer;
+
+use SMW\Elastic\Indexer\IndexerRecoveryJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Elastic\Indexer\IndexerRecoveryJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class IndexerRecoveryJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+ private $title;
+ private $cache;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection = $this->getMockBuilder( '\SMW\Elastic\Connection\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Cache', $this->cache );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ IndexerRecoveryJob::class,
+ new IndexerRecoveryJob( $this->title )
+ );
+ }
+
+ public function testRun_Index() {
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'getConfig' )
+ ->will( $this->returnValue( ( new \SMW\Options() ) ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' );
+
+ $instance = new IndexerRecoveryJob(
+ $this->title,
+ [ 'index' => 'Foo#0##']
+ );
+
+ $instance->run();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerTest.php
new file mode 100644
index 00000000..51edfe84
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/IndexerTest.php
@@ -0,0 +1,208 @@
+<?php
+
+namespace SMW\Tests\Elastic\Indexer;
+
+use SMW\Elastic\Indexer\Indexer;
+use SMW\Services\ServicesContainer;
+use SMW\DIWikiPage;
+
+/**
+ * @covers \SMW\Elastic\Indexer\Indexer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class IndexerTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $servicesContainer;
+ private $logger;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->servicesContainer = new ServicesContainer();
+
+ $this->logger = $this->getMockBuilder( '\Psr\Log\NullLogger' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Indexer::class,
+ new Indexer( $this->store, $this->servicesContainer )
+ );
+ }
+
+ public function testSetup() {
+
+ $rollover = $this->getMockBuilder( '\SMW\Elastic\Indexer\Rollover' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $rollover->expects( $this->exactly( 2 ) )
+ ->method( 'update' );
+
+ $this->servicesContainer->add(
+ 'Rollover',
+ function() use( $rollover ) { return $rollover; }
+ );
+
+ $instance = new Indexer(
+ $this->store,
+ $this->servicesContainer
+ );
+
+ $instance->setup();
+ }
+
+ public function testDrop() {
+
+ $rollover = $this->getMockBuilder( '\SMW\Elastic\Indexer\Rollover' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $rollover->expects( $this->exactly( 2 ) )
+ ->method( 'delete' );
+
+ $this->servicesContainer->add(
+ 'Rollover',
+ function() use( $rollover ) { return $rollover; }
+ );
+
+ $instance = new Indexer(
+ $this->store,
+ $this->servicesContainer
+ );
+
+ $instance->drop();
+ }
+
+ public function testTextIndex() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+ $subject->setId( 42 );
+
+ $changeDiff = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeDiff' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $changeDiff->expects( $this->once() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeDiff->expects( $this->once() )
+ ->method( 'getDataOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $bulk = $this->getMockBuilder( '\SMW\Elastic\Indexer\Bulk' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $bulk->expects( $this->once() )
+ ->method( 'upsert' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'text_raw' => 'Bar' ] ) );
+
+ $this->servicesContainer->add(
+ 'Bulk',
+ function() use( $bulk ) { return $bulk; }
+ );
+
+ $instance = new Indexer(
+ $this->store,
+ $this->servicesContainer
+ );
+
+ $instance->setLogger( $this->logger );
+ $instance->index( $changeDiff, 'Bar' );
+ }
+
+ /**
+ * @dataProvider textLinksProvider
+ */
+ public function testRemoveLinks( $text, $expected ) {
+
+ $instance = new Indexer(
+ $this->store,
+ $this->servicesContainer
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->removeLinks( $text )
+ );
+ }
+
+ public function textLinksProvider() {
+
+ yield [
+ 'abc',
+ 'abc'
+ ];
+
+ yield [
+ '{{DEFAULTSORT: FOO}}',
+ ''
+ ];
+
+ yield [
+ '{{Foo|bar=foobar}}',
+ 'bar=foobar'
+ ];
+
+ yield [
+ '[[Has foo::Bar]]',
+ 'Bar'
+ ];
+
+ yield [
+ '[[:foo|abc]]',
+ 'abc'
+ ];
+
+ yield [
+ 'abc [[:foo|abc]]',
+ 'abc abc'
+ ];
+
+ yield [
+ '[[:|abc]]',
+ '[[:|abc]]'
+ ];
+
+ yield [
+ '[[:abc]]',
+ ':abc'
+ ];
+
+ yield [
+ 'abc [[abc]]',
+ 'abc abc'
+ ];
+
+ yield [
+ '[[abc]] abc [[:bar|foobar]]',
+ 'abc abc foobar'
+ ];
+
+ yield [
+ '[[:Spécial%3ARequêter&cl=Yzo1jUEKwzAMBF8T3RKMS486tPTQb8iJjE3sGCSH9PlVGgpzWLRi9oPj_Wm8SUfvtr0GluH2OPF2fxkQm1TqGKTR0ikUhpJr7uids7StSKVAYlpYFDW1A5RJ5lQocMFpmgbv4i49mdo7Yd1LV5gLqb03-SmtOPKa_1nrcS2dPUITcyPpDC1G5Y4OKuXtGvgC|foo]]',
+ 'foo'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RebuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RebuilderTest.php
new file mode 100644
index 00000000..5be73b67
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RebuilderTest.php
@@ -0,0 +1,264 @@
+<?php
+
+namespace SMW\Tests\Elastic\Indexer;
+
+use SMW\Elastic\Indexer\Rebuilder;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\Indexer\Rebuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RebuilderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connection;
+ private $indexer;
+ private $propertyTableRowMapper;
+ private $rollover;
+ private $messageReporter;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\Elastic\Connection\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->indexer = $this->getMockBuilder( '\SMW\Elastic\Indexer\Indexer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyTableRowMapper = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableRowMapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->rollover = $this->getMockBuilder( '\SMW\Elastic\Indexer\Rollover' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->messageReporter = $this->getMockBuilder( '\Onoi\MessageReporter\NullMessageReporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Rebuilder::class,
+ new Rebuilder( $this->connection, $this->indexer, $this->propertyTableRowMapper, $this->rollover )
+ );
+ }
+
+ public function testSelect() {
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Rebuilder(
+ $this->connection,
+ $this->indexer,
+ $this->propertyTableRowMapper,
+ $this->rollover
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->select( $store, [] )
+ );
+ }
+
+ public function testDeleteAndSetupIndices() {
+
+ $this->indexer->expects( $this->once() )
+ ->method( 'drop' );
+
+ $this->indexer->expects( $this->once() )
+ ->method( 'setup' );
+
+ $instance = new Rebuilder(
+ $this->connection,
+ $this->indexer,
+ $this->propertyTableRowMapper,
+ $this->rollover
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $instance->deleteAndSetupIndices();
+ }
+
+ public function testCreateIndices() {
+
+ $indices = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists', 'delete', 'existsAlias', 'updateAliases' ] )
+ ->getMock();
+
+ $indices->expects( $this->atLeastOnce() )
+ ->method( 'updateAliases' );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'indices' )
+ ->will( $this->returnValue( $indices ) );
+
+ $this->connection->expects( $this->exactly( 2 ) )
+ ->method( 'setLock' );
+
+ $instance = new Rebuilder(
+ $this->connection,
+ $this->indexer,
+ $this->propertyTableRowMapper,
+ $this->rollover
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $instance->createIndices();
+ }
+
+ public function testSetDefaults() {
+
+ $indices = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists', 'delete', 'close', 'open' ] )
+ ->getMock();
+
+ $indices->expects( $this->atLeastOnce() )
+ ->method( 'open' );
+
+ $indices->expects( $this->atLeastOnce() )
+ ->method( 'close' );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'indices' )
+ ->will( $this->returnValue( $indices ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'hasIndex' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->exactly( 2 ) )
+ ->method( 'releaseLock' );
+
+ $instance = new Rebuilder(
+ $this->connection,
+ $this->indexer,
+ $this->propertyTableRowMapper,
+ $this->rollover
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $instance->setDefaults();
+ }
+
+ public function testDelete() {
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'delete' );
+
+ $instance = new Rebuilder(
+ $this->connection,
+ $this->indexer,
+ $this->propertyTableRowMapper,
+ $this->rollover
+ );
+
+ $instance->delete( 42 );
+ }
+
+ public function testRebuild() {
+
+ $options = $this->getMockBuilder( '\SMW\Options' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeDiff' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'newChangeDiff' )
+ ->will( $this->returnValue( $changeDiff ) );
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $this->propertyTableRowMapper->expects( $this->any() )
+ ->method( 'newChangeOp' )
+ ->will( $this->returnValue( $changeOp ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'getConfig' )
+ ->will( $this->returnValue( $options ) );
+
+ $this->indexer->expects( $this->once() )
+ ->method( 'index' );
+
+ $instance = new Rebuilder(
+ $this->connection,
+ $this->indexer,
+ $this->propertyTableRowMapper,
+ $this->rollover
+ );
+
+ $instance->rebuild( 42, $semanticData );
+ }
+
+ public function testRefresh() {
+
+ $this->connection->expects( $this->any() )
+ ->method( 'hasIndex' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'refresh' );
+
+ $instance = new Rebuilder(
+ $this->connection,
+ $this->indexer,
+ $this->propertyTableRowMapper,
+ $this->rollover
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $instance->refresh();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/ReplicationStatusTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/ReplicationStatusTest.php
new file mode 100644
index 00000000..3d66e991
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/ReplicationStatusTest.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace SMW\Tests\Elastic\Indexer;
+
+use SMW\Elastic\Indexer\ReplicationStatus;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\Indexer\ReplicationStatus
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ReplicationStatusTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connection;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\Elastic\Connection\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ReplicationStatus::class,
+ new ReplicationStatus( $this->connection )
+ );
+ }
+
+ public function testGet_OnUnknownKeyThrowsException() {
+
+ $instance = new ReplicationStatus(
+ $this->connection
+ );
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->get( 'Foo' );
+ }
+
+ public function testGet_refresh_interval() {
+
+ $settings = [
+ 'Foo' => [
+ 'settings' => [
+ 'index' => [
+ 'refresh_interval' => 42
+ ]
+ ]
+ ]
+ ];
+
+ $this->connection->expects( $this->once() )
+ ->method( 'getSettings' )
+ ->will( $this->returnValue( $settings ) );
+
+ $instance = new ReplicationStatus(
+ $this->connection
+ );
+
+ $this->assertEquals(
+ 42,
+ $instance->get( 'refresh_interval' )
+ );
+ }
+
+ public function testGet_last_update() {
+
+ $res = [
+ 'hits' => [
+ 'hits' => [
+ [
+ '_source' => [
+ 'P:29' => [
+ 'datField' => [ 2458322.0910764 ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ];
+
+ $this->connection->expects( $this->once() )
+ ->method( 'search' )
+ ->will( $this->returnValue( [ $res, [] ] ) );
+
+ $instance = new ReplicationStatus(
+ $this->connection
+ );
+
+ $this->assertEquals(
+ '2018-07-22 14:11:09',
+ $instance->get( 'last_update' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RolloverTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RolloverTest.php
new file mode 100644
index 00000000..2e8fbd7c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Indexer/RolloverTest.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace SMW\Tests\Elastic\Indexer;
+
+use SMW\Elastic\Indexer\Rollover;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\Indexer\Rollover
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RolloverTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connection;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\Elastic\Connection\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Rollover::class,
+ new Rollover( $this->connection )
+ );
+ }
+
+ public function testRollover() {
+
+ $indices = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists', 'delete', 'existsAlias', 'updateAliases' ] )
+ ->getMock();
+
+ $indices->expects( $this->once() )
+ ->method( 'updateAliases' );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'indices' )
+ ->will( $this->returnValue( $indices ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'releaseLock' );
+
+ $instance = new Rollover(
+ $this->connection
+ );
+
+ $instance->rollover( 'Foo', 'v2' );
+ }
+
+ public function testUpdate() {
+
+ $indices = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists', 'delete', 'existsAlias', 'updateAliases' ] )
+ ->getMock();
+
+ $indices->expects( $this->once() )
+ ->method( 'updateAliases' );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'indices' )
+ ->will( $this->returnValue( $indices ) );
+
+ $instance = new Rollover(
+ $this->connection
+ );
+
+ $instance->update( 'Foo' );
+ }
+
+ public function testDelete() {
+
+ $indices = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists', 'delete', 'existsAlias' ] )
+ ->getMock();
+
+ $indices->expects( $this->exactly( 3 ) )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $indices->expects( $this->exactly( 3 ) )
+ ->method( 'delete' );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'indices' )
+ ->will( $this->returnValue( $indices ) );
+
+ $instance = new Rollover(
+ $this->connection
+ );
+
+ $instance->delete( 'Foo' );
+ }
+
+ public function testUpdate_OnNoConnectionThrowsException() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new Rollover(
+ $this->connection
+ );
+
+ $this->setExpectedException( '\SMW\Elastic\Exception\NoConnectionException' );
+ $instance->update( 'Foo' );
+ }
+
+ public function testDelete_OnNoConnectionThrowsException() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new Rollover(
+ $this->connection
+ );
+
+ $this->setExpectedException( '\SMW\Elastic\Exception\NoConnectionException' );
+ $instance->delete( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Lookup/ProximityPropertyValueLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Lookup/ProximityPropertyValueLookupTest.php
new file mode 100644
index 00000000..aef58370
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/Lookup/ProximityPropertyValueLookupTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\Elastic\Lookup;
+
+use SMW\Elastic\Lookup\ProximityPropertyValueLookup;
+use SMW\Tests\PHPUnitCompat;
+use SMW\DIProperty;
+use SMW\RequestOptions;
+
+/**
+ * @covers \SMW\Elastic\Lookup\ProximityPropertyValueLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ProximityPropertyValueLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $logger;
+ private $store;
+ private $elasticClient;
+
+ protected function setUp() {
+
+ $this->logger = $this->getMockBuilder( '\Psr\Log\LoggerInterface' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID' ] )
+ ->getMock();
+
+ $this->idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->onConsecutiveCalls( 42, 1001, 9000, 110001 ) );
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'getConnection' ] )
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $this->idTable ) );
+
+ $this->elasticClient = $this->getMockBuilder( '\SMW\Elastic\Connection\Client' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->elasticClient ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ProximityPropertyValueLookup::class,
+ new ProximityPropertyValueLookup( $this->store )
+ );
+ }
+
+ public function testLookup_AnyValue() {
+
+ $params = [
+ 'index' => null,
+ 'type' => 'data',
+ 'body' => [
+ '_source' => [ 'P:42.wpgField' ],
+ 'from' => 0,
+ 'size' => 500,
+ 'query' => [
+ 'exists' => [ 'field' => 'P:42.wpgField' ]
+ ]
+ ]
+ ];
+
+ $this->elasticClient->expects( $this->once() )
+ ->method( 'search' )
+ ->with( $this->equalTo( $params ) );
+
+ $instance = new ProximityPropertyValueLookup(
+ $this->store
+ );
+
+ $instance->lookup( new DIProperty( 'Foo' ), '', new RequestOptions() );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/AggregationsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/AggregationsTest.php
new file mode 100644
index 00000000..cdcc45da
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/AggregationsTest.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine;
+
+use SMW\Elastic\QueryEngine\Aggregations;
+use SMW\Elastic\QueryEngine\FieldMapper;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\Aggregations
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class AggregationsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Aggregations::class,
+ new Aggregations()
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testResolve( $parameters, $expected ) {
+
+ $instance = new Aggregations( $parameters );
+
+ $this->assertEquals(
+ $expected,
+ (string)$instance
+ );
+ }
+
+ public function parametersProvider() {
+
+ $fieldMapper = new FieldMapper();
+
+ yield [
+ [],
+ '[]'
+ ];
+
+ yield [
+ $fieldMapper->aggs_terms( 'test_1', 'category' ),
+ '{"aggregations":{"test_1":{"terms":{"field":"category"}}}}'
+ ];
+
+ yield [
+ $fieldMapper->aggs_terms( 'test_2', 'category', [ 'size' => 5 ] ),
+ '{"aggregations":{"test_2":{"terms":{"field":"category","size":5}}}}'
+ ];
+
+ yield [
+ [
+ $fieldMapper->aggs_terms( 'test_1', 'foo' ),
+ $fieldMapper->aggs_terms( 'test_2', 'bar' )
+ ],
+ '{"aggregations":{"test_1":{"terms":{"field":"foo"}},"test_2":{"terms":{"field":"bar"}}}}'
+ ];
+
+ yield [
+ [
+ new Aggregations( $fieldMapper->aggs_terms( 'test_1', 'foo' ) ),
+ new Aggregations( $fieldMapper->aggs_terms( 'test_2', 'bar' ) )
+ ],
+ '{"aggregations":{"test_1":{"terms":{"field":"foo"}},"test_2":{"terms":{"field":"bar"}}}}'
+ ];
+
+ // https://www.elastic.co/blog/intro-to-Aggregations-pt-2-sub-Aggregations
+ $aggs = new Aggregations(
+ $fieldMapper->aggs_terms( 'all_boroughs', 'borough' )
+ );
+
+ $aggs->addSubAggregations(
+ new Aggregations(
+ $fieldMapper->aggs_terms( 'cause', 'contributing_factor_vehicle', [ 'size' => 3 ] )
+ )
+ );
+
+ yield [
+ $aggs,
+ '{"aggregations":{"all_boroughs":{"terms":{"field":"borough"},"aggregations":{"cause":{"terms":{"field":"contributing_factor_vehicle","size":3}}}}}}'
+ ];
+
+ $cause = new Aggregations(
+ $fieldMapper->aggs_terms( 'cause', 'contributing_factor_vehicle', [ 'size' => 3 ] )
+ );
+
+ $cause->addSubAggregations(
+ new Aggregations(
+ $fieldMapper->aggs_date_histogram( 'incidents_per_month', '@timestamp', 'month' )
+ )
+ );
+
+ $aggs = new Aggregations(
+ $fieldMapper->aggs_terms( 'all_boroughs', 'borough' )
+ );
+
+ $aggs->addSubAggregations(
+ $cause
+ );
+
+ yield [
+ $aggs,
+ '{"aggregations":{"all_boroughs":{"terms":{"field":"borough"},"aggregations":{"cause":{"terms":{"field":"contributing_factor_vehicle","size":3},"aggregations":{"incidents_per_month":{"date_histogram":{"field":"@timestamp","interval":"month"}}}}}}}}'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ConditionTest.php
new file mode 100644
index 00000000..53bcf587
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ConditionTest.php
@@ -0,0 +1,144 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine;
+
+use SMW\Elastic\QueryEngine\Condition;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\Condition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ConditionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Condition::class,
+ new Condition()
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testResolveConditionParameters( $paramsters, $type, $expected ) {
+
+ $instance = new Condition( $paramsters );
+ $instance->type( $type );
+
+ $this->assertEquals(
+ $expected,
+ $instance->__toString()
+ );
+ }
+
+ /**
+ * @dataProvider typeProvider
+ */
+ public function testType( $type, $expected ) {
+
+ $instance = new Condition( [] );
+ $instance->type( $type );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getType()
+ );
+ }
+
+ public function testConditionLogs() {
+
+ $cond = new Condition( [ 'foobar' ] );
+ $cond->log( 'foo_log' );
+
+ $instance = new Condition( $cond );
+ $instance->log( [ 'test' ] );
+
+ $instance->toArray();
+
+ $this->assertEquals(
+ [ [ 'test' ], [ 'foo_log' ] ],
+ $instance->getLogs()
+ );
+ }
+
+ public function parametersProvider() {
+
+ yield [
+ '',
+ '',
+ '""'
+ ];
+
+ yield [
+ [],
+ '',
+ '[]'
+ ];
+
+ yield [
+ [ 'Foo' => [ 'Bar' ] ],
+ 'must',
+ '{"bool":{"must":{"Foo":["Bar"]}}}'
+ ];
+
+ yield [
+ [ new Condition( [ 'foobar' ] ) ],
+ 'must',
+ '{"bool":{"must":[{"bool":{"must":["foobar"]}}]}}'
+ ];
+
+ $cond = new Condition( [ 'foobar' ] );
+ $cond->type( '' );
+
+ yield [
+ [ $cond ],
+ 'must',
+ '{"bool":{"must":[["foobar"]]}}'
+ ];
+
+ $cond = new Condition( [ 'foobar' ] );
+ $cond->type( null );
+
+ yield [
+ [ $cond ],
+ 'must',
+ '{"bool":{"must":[["foobar"]]}}'
+ ];
+
+ yield [
+ [ [ new Condition( [ 'foobar' ] ), new Condition( [ 'bar' ] ) ] ],
+ Condition::TYPE_SHOULD,
+ '{"bool":{"should":[[{"bool":{"must":["foobar"]}},{"bool":{"must":["bar"]}}]]}}'
+ ];
+ }
+
+ public function typeProvider() {
+
+ yield [
+ 'must',
+ Condition::TYPE_MUST
+ ];
+
+ yield [
+ 'must_not',
+ Condition::TYPE_MUST_NOT
+ ];
+
+ yield [
+ 'should',
+ Condition::TYPE_SHOULD
+ ];
+
+ yield [
+ 'filter',
+ Condition::TYPE_FILTER
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php
new file mode 100644
index 00000000..a47df9f8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine\DescriptionInterpreters;
+
+use SMW\Elastic\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter;
+use SMW\DIWikiPage;
+use SMW\Query\DescriptionFactory;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ClassDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $conditionBuilder;
+
+ public function setUp() {
+
+ $this->conditionBuilder = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getID', 'findHierarchyMembers' ] )
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ClassDescriptionInterpreter::class,
+ new ClassDescriptionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ /**
+ * @dataProvider classDescriptionProvider
+ */
+ public function testInterpretDescription( $description, $isConjunction, $hierarchyMembers, $expected ) {
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'getID' )
+ ->will( $this->onConsecutiveCalls( 42, 1001, 9000, 110001 ) );
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'findHierarchyMembers' )
+ ->will( $this->returnValue( $hierarchyMembers ) );
+
+ $instance = new ClassDescriptionInterpreter(
+ $this->conditionBuilder
+ );
+
+ $condition = $instance->interpretDescription(
+ $description,
+ $isConjunction
+ );
+
+ $this->assertEquals(
+ $expected,
+ $condition
+ );
+ }
+
+ public function classDescriptionProvider() {
+
+ $descriptionFactory = new DescriptionFactory();
+ $cat_foo = DIWikiPage::newFromText( 'Foo', NS_CATEGORY );
+ $cat_bar = DIWikiPage::newFromText( 'Bar', NS_CATEGORY );
+
+ yield [
+ $descriptionFactory->newClassDescription( $cat_foo ),
+ false,
+ [],
+ '{"bool":{"filter":[{"term":{"P:42.wpgID":1001}}]}}'
+ ];
+
+ yield [
+ $descriptionFactory->newClassDescription( $cat_foo ),
+ true,
+ [],
+ '{"bool":{"filter":[{"term":{"P:42.wpgID":1001}}]}}'
+ ];
+
+ // Categories
+ $classDescription = $descriptionFactory->newClassDescription( $cat_foo );
+ $classDescription->addClass( $cat_bar );
+
+ yield [
+ $classDescription,
+ false,
+ [],
+ '{"bool":{"should":[{"term":{"P:42.wpgID":1001}},{"term":{"P:42.wpgID":9000}}]}}'
+ ];
+
+ yield [
+ $classDescription,
+ true,
+ [],
+ '{"bool":{"should":[{"term":{"P:42.wpgID":1001}},{"term":{"P:42.wpgID":9000}}]}}'
+ ];
+
+ // HierarchyMembers
+ yield [
+ $descriptionFactory->newClassDescription( $cat_foo ),
+ false,
+ [ 5000, 5001 ],
+ '{"bool":{"filter":[{"bool":{"should":[{"term":{"P:42.wpgID":1001}},{"terms":{"P:42.wpgID":[5000,5001]}}]}}]}}'
+ ];
+
+ yield [
+ $descriptionFactory->newClassDescription( $cat_foo ),
+ true,
+ [ 5000, 5001 ],
+ '{"bool":{"filter":[{"bool":{"should":[{"term":{"P:42.wpgID":1001}},{"terms":{"P:42.wpgID":[5000,5001]}}]}}]}}'
+ ];
+
+ yield [
+ $classDescription,
+ false,
+ [ 5000, 5001 ],
+ '{"bool":{"should":[{"bool":{"should":[{"term":{"P:42.wpgID":1001}},{"terms":{"P:42.wpgID":[5000,5001]}}]}},{"bool":{"should":[{"term":{"P:42.wpgID":9000}},{"terms":{"P:42.wpgID":[5000,5001]}}]}}]}}'
+ ];
+
+ // Negation
+ $classDescription = $descriptionFactory->newClassDescription( $cat_foo );
+ $classDescription->isNegation = true;
+
+ yield [
+ $classDescription,
+ false,
+ [],
+ '{"bool":{"must_not":[{"term":{"P:42.wpgID":1001}}]}}'
+ ];
+
+ yield [
+ $classDescription,
+ true,
+ [],
+ '{"bool":{"must_not":[{"term":{"P:42.wpgID":1001}}]}}'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php
new file mode 100644
index 00000000..cac182be
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine\DescriptionInterpreters;
+
+use SMW\Elastic\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter;
+use SMW\DIWikiPage;
+use SMW\Query\DescriptionFactory;
+use SMW\Tests\TestEnvironmentTrait;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ConceptDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $conditionBuilder;
+ private $descriptionFactory;
+ private $queryParser;
+
+ public function setUp() {
+
+ $this->descriptionFactory = new DescriptionFactory();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parameters = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\TermsLookup\Parameters' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->termsLookup = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\TermsLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->termsLookup->expects( $this->any() )
+ ->method( 'newParameters' )
+ ->will( $this->returnValue( $parameters ) );
+
+ $this->conditionBuilder = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getTermsLookup', 'getStore', 'getID', 'interpretDescription' ] )
+ ->getMock();
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $this->store ) );
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'getTermsLookup' )
+ ->will( $this->returnValue( $this->termsLookup ) );
+
+ $this->queryParser = $this->getMockBuilder( '\SMW\Query\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConceptDescriptionInterpreter::class,
+ new ConceptDescriptionInterpreter( $this->conditionBuilder, $this->queryParser )
+ );
+ }
+
+ public function testInterpretDescription_EmptyConcept() {
+
+ $instance = new ConceptDescriptionInterpreter(
+ $this->conditionBuilder,
+ $this->queryParser
+ );
+
+ $conceptDescription = $this->descriptionFactory->newConceptDescription(
+ DIWikiPage::newFromText( 'Foo', SMW_NS_CONCEPT )
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->interpretDescription( $conceptDescription )
+ );
+ }
+
+ public function testInterpretDescription_AvailableConceptQuery() {
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'interpretDescription' )
+ ->will( $this->returnValue( $this->conditionBuilder->newCondition( [ 'Foo' ] ) ) );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $concept = $this->getMockBuilder( '\SMWDIConcept' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $concept ] ) );
+
+ $this->queryParser->expects( $this->any() )
+ ->method( 'getQueryDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $instance = new ConceptDescriptionInterpreter(
+ $this->conditionBuilder,
+ $this->queryParser
+ );
+
+ $conceptDescription = $this->descriptionFactory->newConceptDescription(
+ DIWikiPage::newFromText( 'Foo', SMW_NS_CONCEPT )
+ );
+
+ $this->assertEquals(
+ '{"bool":{"must":["Foo"]}}',
+ $instance->interpretDescription( $conceptDescription )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php
new file mode 100644
index 00000000..ce1b4fa4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine\DescriptionInterpreters;
+
+use SMW\Elastic\QueryEngine\DescriptionInterpreters\ConjunctionInterpreter;
+use SMW\DIWikiPage;
+use SMW\Query\DescriptionFactory;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\DescriptionInterpreters\ConjunctionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ConjunctionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $conditionBuilder;
+
+ public function setUp() {
+
+ $this->descriptionFactory = new DescriptionFactory();
+
+ $this->conditionBuilder = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'interpretDescription' ] )
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConjunctionInterpreter::class,
+ new ConjunctionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testInterpretDescription_Empty() {
+
+ $instance = new ConjunctionInterpreter(
+ $this->conditionBuilder
+ );
+
+ $condition = $instance->interpretDescription(
+ $this->descriptionFactory->newConjunction( [] )
+ );
+
+ $this->assertEquals(
+ [],
+ $condition
+ );
+ }
+
+ public function testInterpretDescription_NotEmpty() {
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'interpretDescription' )
+ ->will( $this->returnValue( $this->conditionBuilder->newCondition( [ 'Foo' ] ) ) );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->any() )
+ ->method( 'getPrintRequests' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new ConjunctionInterpreter(
+ $this->conditionBuilder
+ );
+
+ $condition = $instance->interpretDescription(
+ $this->descriptionFactory->newConjunction( [ $description ] )
+ );
+
+ $this->assertEquals(
+ '{"bool":{"must":[{"bool":{"must":["Foo"]}}]}}',
+ $condition
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php
new file mode 100644
index 00000000..9671b96e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine\DescriptionInterpreters;
+
+use SMW\Elastic\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter;
+use SMW\DIWikiPage;
+use SMW\Query\DescriptionFactory;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class NamespaceDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $conditionBuilder;
+
+ public function setUp() {
+
+ $this->descriptionFactory = new DescriptionFactory();
+
+ $this->conditionBuilder = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( null )
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ NamespaceDescriptionInterpreter::class,
+ new NamespaceDescriptionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testInterpretDescription_NotPartOfAConjunction() {
+
+ $instance = new NamespaceDescriptionInterpreter(
+ $this->conditionBuilder
+ );
+
+ $condition = $instance->interpretDescription(
+ $this->descriptionFactory->newNamespaceDescription( NS_MAIN ),
+ false
+ );
+
+ $this->assertEquals(
+ '{"bool":{"filter":{"term":{"subject.namespace":0}}}}',
+ $condition
+ );
+ }
+
+ public function testInterpretDescription_IsPartOfAConjunction() {
+
+ $instance = new NamespaceDescriptionInterpreter(
+ $this->conditionBuilder
+ );
+
+ $condition = $instance->interpretDescription(
+ $this->descriptionFactory->newNamespaceDescription( NS_MAIN ),
+ true
+ );
+
+ $this->assertEquals(
+ '{"term":{"subject.namespace":0}}',
+ $condition
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/SomeValueInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/SomeValueInterpreterTest.php
new file mode 100644
index 00000000..7dff7713
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/SomeValueInterpreterTest.php
@@ -0,0 +1,369 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine\DescriptionInterpreters;
+
+use SMW\Elastic\QueryEngine\DescriptionInterpreters\SomeValueInterpreter;
+use SMW\DIWikiPage;
+use SMW\Options;
+use SMW\Query\DescriptionFactory;
+use SMW\DataItemFactory;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\DescriptionInterpreters\SomeValueInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SomeValueInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $conditionBuilder;
+ private $descriptionFactory;
+ private $dataItemFactory;
+
+ public function setUp() {
+
+ $this->descriptionFactory = new DescriptionFactory();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->conditionBuilder = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getID' ] )
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SomeValueInterpreter::class,
+ new SomeValueInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ public function testInterpretDescription_MissingPropertyThrowsException() {
+
+ $instance = new SomeValueInterpreter(
+ $this->conditionBuilder
+ );
+
+ $options = [];
+
+ $description = $this->descriptionFactory->newValueDescription(
+ $this->dataItemFactory->newDIWikiPage( 'Foo' )
+ );
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->interpretDescription( $description, $options );
+ }
+
+ public function testInterpretDescription_MissingPIDThrowsException() {
+
+ $instance = new SomeValueInterpreter(
+ $this->conditionBuilder
+ );
+
+ $options = [
+ 'property' => $this->dataItemFactory->newDIProperty( 'Bar' )
+ ];
+
+ $description = $this->descriptionFactory->newValueDescription(
+ $this->dataItemFactory->newDIWikiPage( 'Foo' )
+ );
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->interpretDescription( $description, $options );
+ }
+
+ /**
+ * @dataProvider numberValueProvider
+ */
+ public function testInterpretDescription_NumberValue( $dataItem, $comparator, $options, $expected ) {
+
+ $instance = new SomeValueInterpreter(
+ $this->conditionBuilder
+ );
+
+ $description = $this->descriptionFactory->newValueDescription(
+ $dataItem,
+ null,
+ $comparator
+ );
+
+ $condition = $instance->interpretDescription(
+ $description,
+ $options
+ );
+
+ $this->assertEquals(
+ $expected,
+ (string)$condition
+ );
+ }
+
+ /**
+ * @dataProvider timeValueProvider
+ */
+ public function testInterpretDescription_TimeValue( $dataItem, $comparator, $options, $expected ) {
+
+ $instance = new SomeValueInterpreter(
+ $this->conditionBuilder
+ );
+
+ $description = $this->descriptionFactory->newValueDescription(
+ $dataItem,
+ null,
+ $comparator
+ );
+
+ $condition = $instance->interpretDescription(
+ $description,
+ $options
+ );
+
+ $this->assertEquals(
+ $expected,
+ (string)$condition
+ );
+ }
+
+ /**
+ * @dataProvider textValueProvider
+ */
+ public function testInterpretDescription_TextValue( $dataItem, $comparator, $options, $expected ) {
+
+ $instance = new SomeValueInterpreter(
+ $this->conditionBuilder
+ );
+
+ $description = $this->descriptionFactory->newValueDescription(
+ $dataItem,
+ null,
+ $comparator
+ );
+
+ $condition = $instance->interpretDescription(
+ $description,
+ $options
+ );
+
+ $this->assertEquals(
+ $expected,
+ (string)$condition
+ );
+ }
+
+ /**
+ * @dataProvider pageValueProvider
+ */
+ public function testInterpretDescription_PageValue( $dataItem, $comparator, $options, $expected ) {
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'getID' )
+ ->will( $this->onConsecutiveCalls( 42, 1001, 9000, 110001 ) );
+
+ $this->conditionBuilder->setOptions( new Options(
+ [
+ 'cjk.best.effort.proximity.match' => true
+ ]
+ ) );
+
+ $instance = new SomeValueInterpreter(
+ $this->conditionBuilder
+ );
+
+ $description = $this->descriptionFactory->newValueDescription(
+ $dataItem,
+ null,
+ $comparator
+ );
+
+ $condition = $instance->interpretDescription(
+ $description,
+ $options
+ );
+
+ $this->assertEquals(
+ $expected,
+ (string)$condition
+ );
+ }
+
+ public function numberValueProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $options = [
+ 'property' => $dataItemFactory->newDIProperty( 'Bar' ),
+ 'pid' => 'P:42',
+ 'field' => 'numField',
+ 'type' => 'must'
+ ];
+
+ $dataItem = $dataItemFactory->newDINumber( 123 );
+
+ yield [
+ $dataItem,
+ SMW_CMP_EQ,
+ $options,
+ '{"bool":{"filter":{"term":{"P:42.numField":123}}}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_NEQ,
+ $options,
+ '{"bool":{"must_not":{"term":{"P:42.numField":123}}}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_LESS,
+ $options,
+ '{"bool":{"must":[{"range":{"P:42.numField":{"lt":123}}}]}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_GRTR,
+ $options,
+ '{"bool":{"must":[{"range":{"P:42.numField":{"gt":123}}}]}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_LEQ,
+ $options,
+ '{"bool":{"must":[{"range":{"P:42.numField":{"lte":123}}}]}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_GEQ,
+ $options,
+ '{"bool":{"must":[{"range":{"P:42.numField":{"gte":123}}}]}}'
+ ];
+
+ // This form is actually handled differently using a compound
+ // [[Has number::~123]] -> [[Has number:: <q>[[≥0]] [[≤123]]</q> ]]
+ yield [
+ $dataItem,
+ SMW_CMP_LIKE,
+ $options,
+ '{"bool":{"must":[{"match":{"P:42.numField":{"query":123,"operator":"and"}}}]}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_NLKE,
+ $options,
+ '{"bool":{"must_not":[{"match":{"P:42.numField":{"query":123,"operator":"and"}}}]}}'
+ ];
+ }
+
+ public function timeValueProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $options = [
+ 'property' => $dataItemFactory->newDIProperty( 'Bar' ),
+ 'pid' => 'P:42',
+ 'field' => 'datField',
+ 'type' => 'must'
+ ];
+
+ $dataItem = $dataItemFactory->newDITime( 1, 1970, 12, 12, 12, 12, 12 );
+
+ yield [
+ $dataItem,
+ SMW_CMP_EQ,
+ $options,
+ '{"bool":{"filter":{"term":{"P:42.datField":2440933.0084722}}}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_NEQ,
+ $options,
+ '{"bool":{"must_not":{"term":{"P:42.datField":2440933.0084722}}}}'
+ ];
+ }
+
+ public function textValueProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $options = [
+ 'property' => $dataItemFactory->newDIProperty( 'Bar' ),
+ 'pid' => 'P:42',
+ 'field' => 'txtField',
+ 'type' => 'must'
+ ];
+
+ $dataItem = $dataItemFactory->newDIBlob( '*test*' );
+
+ yield [
+ $dataItem,
+ SMW_CMP_EQ,
+ $options,
+ '{"bool":{"filter":{"term":{"P:42.txtField.keyword":"*test*"}}}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_LIKE,
+ $options,
+ '{"bool":{"must":{"query_string":{"fields":["P:42.txtField","P:42.txtField.keyword"],"query":"*test*"}}}}'
+ ];
+ }
+
+ public function pageValueProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $options = [
+ 'property' => $dataItemFactory->newDIProperty( 'Bar' ),
+ 'pid' => 'P:42',
+ 'field' => 'wpgID',
+ 'type' => 'must'
+ ];
+
+ $dataItem = $dataItemFactory->newDIWikiPage( 'test' );
+
+ yield [
+ $dataItem,
+ SMW_CMP_EQ,
+ $options,
+ '{"bool":{"filter":{"term":{"P:42.wpgID":42}}}}'
+ ];
+
+ $options = [
+ 'property' => $dataItemFactory->newDIProperty( 'Bar' ),
+ 'pid' => 'P:42',
+ 'field' => 'wpgField',
+ 'type' => 'must'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_LIKE,
+ $options,
+ '{"bool":{"must":{"query_string":{"fields":["P:42.wpgField"],"query":"+test"}}}}'
+ ];
+
+ $dataItem = $dataItemFactory->newDIWikiPage( '*テスト*' );
+
+ yield [
+ $dataItem,
+ SMW_CMP_LIKE,
+ $options,
+ '{"bool":{"must":[{"match_phrase":{"P:42.wpgField":"テスト"}}]}}'
+ ];
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php
new file mode 100644
index 00000000..2ce13301
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine\DescriptionInterpreters;
+
+use SMW\Elastic\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter;
+use SMW\DIWikiPage;
+use SMW\Query\DescriptionFactory;
+use SMW\DataItemFactory;
+use SMW\Options;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ValueDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $conditionBuilder;
+
+ public function setUp() {
+
+ $this->descriptionFactory = new DescriptionFactory();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->conditionBuilder = $this->getMockBuilder( '\SMW\Elastic\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getID' ] )
+ ->getMock();
+
+ $this->conditionBuilder->expects( $this->any() )
+ ->method( 'getID' )
+ ->will( $this->onConsecutiveCalls( 42, 1001, 9000, 110001 ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ValueDescriptionInterpreter::class,
+ new ValueDescriptionInterpreter( $this->conditionBuilder )
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testInterpretDescription( $dataItem, $comparator, $options, $expected ) {
+
+ $this->conditionBuilder->setOptions( new Options(
+ [
+ 'cjk.best.effort.proximity.match' => true
+ ]
+ ) );
+
+ $instance = new ValueDescriptionInterpreter(
+ $this->conditionBuilder
+ );
+
+ $description = $this->descriptionFactory->newValueDescription(
+ $dataItem,
+ null,
+ $comparator
+ );
+
+ $condition = $instance->interpretDescription(
+ $description,
+ $options
+ );
+
+ $this->assertEquals(
+ $expected,
+ (string)$condition
+ );
+ }
+
+ public function valueProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $options = [
+ 'property' => $dataItemFactory->newDIProperty( 'Bar' ),
+ 'pid' => 'P:42',
+ 'field' => 'wpgID',
+ 'type' => 'must'
+ ];
+
+ $dataItem = $dataItemFactory->newDIWikiPage( 'test' );
+
+ yield [
+ $dataItem,
+ SMW_CMP_EQ,
+ $options,
+ '{"bool":{"must":{"terms":{"_id":[42]}}}}'
+ ];
+
+ yield [
+ $dataItem,
+ SMW_CMP_LIKE,
+ $options,
+ '{"bool":{"must":[{"match":{"subject.sortkey":"test"}}]}}'
+ ];
+
+ // wide.proximity.fields
+ $dataItem = $dataItemFactory->newDIWikiPage( '~*test*' );
+
+ yield [
+ $dataItem,
+ SMW_CMP_LIKE,
+ $options,
+ '{"bool":{"must":{"query_string":{"fields":["text_copy"],"query":"*test*","minimum_should_match":1}}}}'
+ ];
+
+ // wide.proximity.fields
+ // cjk.best.effort.proximity.match
+ $dataItem = $dataItemFactory->newDIWikiPage( '~*テスト*' );
+
+ yield [
+ $dataItem,
+ SMW_CMP_LIKE,
+ $options,
+ '{"bool":{"must":[{"multi_match":{"fields":["text_copy"],"query":"テスト","type":"phrase"}}]}}'
+ ];
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ExcerptsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ExcerptsTest.php
new file mode 100644
index 00000000..dc3dc7bd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/ExcerptsTest.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine;
+
+use SMW\Elastic\QueryEngine\Excerpts;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\Excerpts
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ExcerptsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Excerpts::class,
+ new Excerpts()
+ );
+ }
+
+ public function testGetExcerpt_StrippedTagsOnString() {
+
+ $instance = new Excerpts();
+
+ $instance->addExcerpt( 'Foo', '<div style="display:none;">Foo<em>bar</em></div>' );
+
+ $this->assertEquals(
+ 'Foo<em>bar</em>',
+ $instance->getExcerpt( 'Foo' )
+ );
+ }
+
+ public function testGetExcerpt_StrippedTagsOnArray() {
+
+ $instance = new Excerpts();
+
+ $instance->addExcerpt( 'Bar', [
+ 'test_field' => [ '<div style="display:none;">Foo<em>bar</em></div>', 'Fooba<em>r</em>' ]
+ ] );
+
+ $this->assertEquals(
+ 'Foo<em>bar</em> Fooba<em>r</em>',
+ $instance->getExcerpt( 'Bar' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/FieldMapperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/FieldMapperTest.php
new file mode 100644
index 00000000..8f13bde1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Elastic/QueryEngine/FieldMapperTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\Elastic\QueryEngine;
+
+use SMW\Elastic\QueryEngine\FieldMapper;
+
+/**
+ * @covers \SMW\Elastic\QueryEngine\FieldMapper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FieldMapperTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FieldMapper::class,
+ new FieldMapper()
+ );
+ }
+
+ public function testIsPhrase() {
+
+ $this->assertTrue(
+ FieldMapper::isPhrase( '"Foo bar"' )
+ );
+
+ $this->assertFalse(
+ FieldMapper::isPhrase( 'Foo"bar' )
+ );
+ }
+
+ public function testHasWildcard() {
+
+ $this->assertTrue(
+ FieldMapper::hasWildcard( 'Foo*' )
+ );
+
+ $this->assertFalse(
+ FieldMapper::hasWildcard( 'foo\*' )
+ );
+ }
+
+ /**
+ * @dataProvider aggregationsProvider
+ */
+ public function testAggregations( $method, $params, $expected ) {
+
+ $instance = new FieldMapper();
+
+ $this->assertEquals(
+ $expected,
+ call_user_func_array( [ $instance, $method ], $params )
+ );
+ }
+
+ public function aggregationsProvider() {
+
+ yield [
+ 'aggs',
+ [ 'Foo', 'bar' ],
+ [ 'aggregations' => [ "Foo" => 'bar' ] ]
+ ];
+
+ yield [
+ 'aggs_terms',
+ [ 'Foo', 'bar', [] ],
+ [ 'Foo' => [ 'terms' => [ "field" => 'bar' ] ] ]
+ ];
+
+ yield [
+ 'aggs_significant_terms',
+ [ 'Foo', 'bar', [] ],
+ [ 'Foo' => [ 'significant_terms' => [ "field" => 'bar' ] ] ]
+ ];
+
+ yield [
+ 'aggs_histogram',
+ [ 'Foo', 'bar', 100 ],
+ [ 'Foo' => [ 'histogram' => [ "field" => 'bar', 'interval' => 100 ] ] ]
+ ];
+
+ yield [
+ 'aggs_date_histogram',
+ [ 'Foo', 'bar', 100 ],
+ [ 'Foo' => [ 'date_histogram' => [ "field" => 'bar', 'interval' => 100 ] ] ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EncoderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EncoderTest.php
new file mode 100644
index 00000000..32dc5f14
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EncoderTest.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Encoder;
+
+/**
+ * @covers \SMW\Encoder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class EncoderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\Encoder',
+ new Encoder()
+ );
+ }
+
+ public function testEscape() {
+
+ $this->assertEquals(
+ '-3C-5B-23-26-25!~`+=-7C-2D-5F-5D-3E',
+ Encoder::escape( '<[#&%!~`+=|-_]>' )
+ );
+ }
+
+ public function testUnescape() {
+
+ $this->assertEquals(
+ '<[#&%!~`+=|-_]>',
+ Encoder::unescape( '-3C-5B-23-26-25!~`+=-7C-2D-5F-5D-3E' )
+ );
+ }
+
+ public function testEncode() {
+
+ $this->assertEquals(
+ '%3C%5B%23%26%25%21~%60%2B%3D%7C-_%5D%3E',
+ Encoder::encode( '<[#&%!~`+=|-_]>' )
+ );
+ }
+
+ /**
+ * @dataProvider stringProvider
+ */
+ public function testDecode( $input, $output ) {
+
+ $this->assertEquals(
+ $output,
+ Encoder::decode( $input )
+ );
+ }
+
+ /**
+ * @dataProvider stringProvider
+ */
+ // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.CodeAnalysis.UnusedFunctionParameter
+ public function testEncodeDecode( $input, $output ) { // @codingStandardsIgnoreEnd
+
+ if ( $output === ' ' ) {
+ $output = '';
+ }
+
+ $this->assertEquals(
+ $output,
+ Encoder::decode( Encoder::encode( Encoder::escape( $output ) ) )
+ );
+ }
+
+ public function stringProvider() {
+
+ $provider = [];
+
+ $provider[] = [ ' ', '' ];
+ $provider[] = [ ' &nbsp;', ' ' ];
+
+ $provider[] = [ '2013/11/05', '2013/11/05' ];
+ $provider[] = [ '2013-2F11-2F05', '2013/11/05' ];
+
+ $provider[] = [ '2013$06&30', '2013$06&30' ];
+ $provider[] = [ '2013-2D06-2D30', '2013-06-30' ];
+
+ $provider[] = [ '2013-2406-2630', '2013$06&30' ];
+ $provider[] = [ '2013%2B06%2B30', '2013+06+30' ];
+ // $provider[] = array( '2013-06-30', '2013-06-30' );
+
+ $provider[] = [ '「ã€æ±äº¬', '「ã€æ±äº¬' ];
+ $provider[] = [ 'http:-2F-2F127.0.0.1-2F%E3%80%8C%E3%80%8D%E6%9D%B1%E4%BA%AC/2F-2F', 'http://127.0.0.1/「ã€æ±äº¬/2F/' ];
+
+ $provider[] = [ 'Foo(-3-)', 'Foo(-3-)' ];
+ $provider[] = [ '"Fo"o', '"Fo"o' ];
+
+ $provider[] = [ 'Foo_bar', 'Foo_bar' ];
+ $provider[] = [ 'Has-20url', 'Has url' ];
+
+ $provider[] = [ 'F &oo=?', 'F &oo=?' ];
+ $provider[] = [ 'F+%26oo%3D%3F', 'F+&oo=?' ];
+ $provider[] = [ 'F_%26oo%3D%3F', 'F_&oo=?' ];
+
+ $provider[] = [ 'search&foo=Bar&', 'search&foo=Bar&' ];
+ $provider[] = [ 'âêîôûëïçé', 'âêîôûëïçé' ];
+
+ $provider[] = [ 'Has+Foo%28-3-%29%26', 'Has+Foo(-3-)&' ];
+ $provider[] = [ 'Has_Foo(-3-)%26', 'Has_Foo(-3-)&' ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EnumTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EnumTest.php
new file mode 100644
index 00000000..e79fee8d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EnumTest.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Enum;
+
+/**
+ * @covers \SMW\Enum
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class EnumTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ *@dataProvider constProvider
+ */
+ public function testValidate( $const ) {
+
+ $this->assertInternalType(
+ 'string',
+ $const
+ );
+ }
+
+ public function constProvider() {
+
+ $provider[] = [
+ Enum::OPT_SUSPEND_PURGE
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventHandlerTest.php
new file mode 100644
index 00000000..0413c400
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventHandlerTest.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\EventHandler;
+
+/**
+ * @covers \SMW\EventHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class EventHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ protected function tearDown() {
+ EventHandler::clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $eventDispatcher = $this->getMockBuilder( '\Onoi\EventDispatcher\EventDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\EventHandler',
+ new EventHandler( $eventDispatcher )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\EventHandler',
+ EventHandler::getInstance()
+ );
+ }
+
+ public function testGetEventDispatcher() {
+
+ $eventDispatcher = $this->getMockBuilder( '\Onoi\EventDispatcher\EventDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new EventHandler( $eventDispatcher );
+
+ $this->assertSame(
+ $eventDispatcher,
+ $instance->getEventDispatcher()
+ );
+
+ $this->assertInstanceOf(
+ '\Onoi\EventDispatcher\EventDispatcher',
+ EventHandler::getInstance()->getEventDispatcher()
+ );
+ }
+
+ public function testCanConstructDispatchContext() {
+
+ $eventDispatcher = $this->getMockBuilder( '\Onoi\EventDispatcher\EventDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new EventHandler( $eventDispatcher );
+
+ $this->assertInstanceOf(
+ '\Onoi\EventDispatcher\DispatchContext',
+ $instance->newDispatchContext()
+ );
+ }
+
+ public function testAddCallbackListenerForAdhocRegistration() {
+
+ $eventDispatcher = $this->getMockBuilder( '\Onoi\EventDispatcher\Dispatcher\GenericEventDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $eventDispatcher->expects( $this->once() )
+ ->method( 'addListener' )
+ ->with(
+ $this->equalTo( 'foo' ),
+ $this->anything() );
+
+ $instance = new EventHandler( $eventDispatcher );
+ $instance->addCallbackListener( 'foo', function (){} );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventListenerRegistryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventListenerRegistryTest.php
new file mode 100644
index 00000000..25210fa0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/EventListenerRegistryTest.php
@@ -0,0 +1,229 @@
+<?php
+
+namespace SMW\Tests;
+
+use Onoi\EventDispatcher\EventDispatcherFactory;
+use Onoi\EventDispatcher\EventListenerCollection;
+use SMW\EventListenerRegistry;
+
+/**
+ * @covers \SMW\EventListenerRegistry
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class EventListenerRegistryTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $eventDispatcherFactory;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->eventDispatcherFactory = EventDispatcherFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $eventListenerCollection = $this->getMockBuilder( '\Onoi\EventDispatcher\EventListenerCollection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ EventListenerRegistry::class,
+ new EventListenerRegistry( $eventListenerCollection )
+ );
+ }
+
+ public function testListenerCollection() {
+
+ $eventListenerCollection = $this->getMockBuilder( '\Onoi\EventDispatcher\EventListenerCollection' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'registerCallback' ] )
+ ->getMockForAbstractClass();
+
+ $eventListenerCollection->expects( $this->any() )
+ ->method( 'registerCallback' );
+
+ $instance = new EventListenerRegistry( $eventListenerCollection );
+
+ $this->assertInstanceOf(
+ '\Onoi\EventDispatcher\EventListenerCollection',
+ $instance
+ );
+ }
+
+ public function testCanExecuteRegisteredListeners() {
+
+ $instance = new EventListenerRegistry(
+ $this->eventDispatcherFactory->newGenericEventListenerCollection()
+ );
+
+ $this->verifyExporterResetEvent( $instance );
+ $this->verifyFactboxCacheDeleteEvent( $instance );
+ $this->verifyFactboxCacheDeleteEventOnEmpty( $instance );
+ $this->verifyCachedPropertyValuesPrefetcherResetEvent( $instance );
+ $this->verifyCachedPrefetcherResetEvent( $instance );
+ $this->verifyCachedUpdateMarkerDeleteEvent( $instance );
+ }
+
+ public function verifyExporterResetEvent( EventListenerCollection $instance ) {
+ $this->assertListenerExecuteFor( 'exporter.reset', $instance, null );
+ }
+
+ public function verifyQueryComparatorResetEvent( EventListenerCollection $instance ) {
+ $this->assertListenerExecuteFor( 'query.comparator.reset', $instance, null );
+ }
+
+ public function verifyFactboxCacheDeleteEvent( EventListenerCollection $instance ) {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+
+ $dispatchContext = $this->eventDispatcherFactory->newDispatchContext();
+
+ $dispatchContext->set(
+ 'title',
+ $title
+ );
+
+ $this->assertListenerExecuteFor(
+ 'factbox.cache.delete',
+ $instance,
+ $dispatchContext
+ );
+ }
+
+ public function verifyFactboxCacheDeleteEventOnEmpty( EventListenerCollection $instance ) {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+
+ $dispatchContext = $this->eventDispatcherFactory->newDispatchContext();
+
+ $dispatchContext->set(
+ 'title',
+ ''
+ );
+
+ $this->assertListenerExecuteFor(
+ 'factbox.cache.delete',
+ $instance,
+ $dispatchContext
+ );
+ }
+
+ public function verifyCachedPropertyValuesPrefetcherResetEvent( EventListenerCollection $instance ) {
+
+ $dispatchContext = $this->eventDispatcherFactory->newDispatchContext();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $dispatchContext->set(
+ 'title',
+ $title
+ );
+
+ $this->assertListenerExecuteFor(
+ 'cached.propertyvalues.prefetcher.reset',
+ $instance,
+ $dispatchContext
+ );
+ }
+
+ public function verifyCachedPrefetcherResetEvent( EventListenerCollection $instance ) {
+
+ $dispatchContext = $this->eventDispatcherFactory->newDispatchContext();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $dispatchContext->set(
+ 'title',
+ $title
+ );
+
+ $this->assertListenerExecuteFor(
+ 'cached.prefetcher.reset',
+ $instance,
+ $dispatchContext
+ );
+ }
+
+ public function verifyCachedUpdateMarkerDeleteEvent( EventListenerCollection $instance ) {
+
+ $dispatchContext = $this->eventDispatcherFactory->newDispatchContext();
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject->expects( $this->atLeastOnce() )
+ ->method( 'getHash' );
+
+ $dispatchContext->set(
+ 'subject',
+ $subject
+ );
+
+ $this->assertListenerExecuteFor(
+ 'cached.update.marker.delete',
+ $instance,
+ $dispatchContext
+ );
+ }
+
+ private function assertListenerExecuteFor( $eventName, $instance, $dispatchContext = null ) {
+
+ $executed = false;
+
+ foreach ( $instance->getCollection() as $event => $listeners ) {
+
+ if ( $eventName !== $event ) {
+ continue;
+ }
+
+ foreach ( $listeners as $listener ) {
+ $listener->execute( $dispatchContext );
+ $executed = true;
+ }
+ }
+
+ $this->assertTrue(
+ $executed,
+ "Failed asseting that '{$eventName}' was executed"
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemDeserializationExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemDeserializationExceptionTest.php
new file mode 100644
index 00000000..a3747620
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemDeserializationExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\DataItemDeserializationException;
+
+/**
+ * @covers \SMW\Exception\DataItemDeserializationException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DataItemDeserializationExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new DataItemDeserializationException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\DataItemDeserializationException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\SMW\Exception\DataItemException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemExceptionTest.php
new file mode 100644
index 00000000..46bc76ae
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataItemExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\DataItemException;
+
+/**
+ * @covers \SMW\Exception\DataItemException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DataItemExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new DataItemException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\DataItemException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataTypeLookupExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataTypeLookupExceptionTest.php
new file mode 100644
index 00000000..7b7ee5e6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/DataTypeLookupExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\DataTypeLookupException;
+
+/**
+ * @covers \SMW\Exception\DataTypeLookupException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DataTypeLookupExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new DataTypeLookupException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\DataTypeLookupException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotReadableExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotReadableExceptionTest.php
new file mode 100644
index 00000000..fa98e353
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotReadableExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\FileNotReadableException;
+
+/**
+ * @covers \SMW\Exception\FileNotReadableException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FileNotReadableExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new FileNotReadableException( 'Foo' );
+
+ $this->assertInstanceof(
+ FileNotReadableException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotWritableExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotWritableExceptionTest.php
new file mode 100644
index 00000000..5c9f3cac
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/FileNotWritableExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\FileNotWritableException;
+
+/**
+ * @covers \SMW\Exception\FileNotWritableException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FileNotWritableExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new FileNotWritableException( 'Foo' );
+
+ $this->assertInstanceof(
+ FileNotWritableException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/ParameterNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/ParameterNotFoundExceptionTest.php
new file mode 100644
index 00000000..0421c3c4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/ParameterNotFoundExceptionTest.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\ParameterNotFoundException;
+
+/**
+ * @covers \SMW\Exception\ParameterNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ParameterNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new ParameterNotFoundException( 'foo' );
+
+ $this->assertInstanceof(
+ ParameterNotFoundException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\InvalidArgumentException',
+ $instance
+ );
+ }
+
+ public function testGetName() {
+
+ $instance = new ParameterNotFoundException( 'bar' );
+
+ $this->assertEquals(
+ 'bar',
+ $instance->getName()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PredefinedPropertyLabelMismatchExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PredefinedPropertyLabelMismatchExceptionTest.php
new file mode 100644
index 00000000..d69371b7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PredefinedPropertyLabelMismatchExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\PredefinedPropertyLabelMismatchException;
+
+/**
+ * @covers \SMW\Exception\PredefinedPropertyLabelMismatchException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PredefinedPropertyLabelMismatchExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new PredefinedPropertyLabelMismatchException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\PredefinedPropertyLabelMismatchException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\SMW\Exception\PropertyLabelNotResolvedException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyLabelNotResolvedExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyLabelNotResolvedExceptionTest.php
new file mode 100644
index 00000000..8862221e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyLabelNotResolvedExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\PropertyLabelNotResolvedException;
+
+/**
+ * @covers \SMW\Exception\PropertyLabelNotResolvedException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyLabelNotResolvedExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new PropertyLabelNotResolvedException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\PropertyLabelNotResolvedException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\SMW\Exception\DataItemException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyNotFoundExceptionTest.php
new file mode 100644
index 00000000..a79cb36b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/PropertyNotFoundExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\PropertyNotFoundException;
+
+/**
+ * @covers \SMW\Exception\PropertyNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new PropertyNotFoundException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\PropertyNotFoundException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/RedirectTargetUnresolvableExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/RedirectTargetUnresolvableExceptionTest.php
new file mode 100644
index 00000000..686f7085
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/RedirectTargetUnresolvableExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\RedirectTargetUnresolvableException;
+
+/**
+ * @covers \SMW\Exception\RedirectTargetUnresolvableException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RedirectTargetUnresolvableExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new RedirectTargetUnresolvableException();
+
+ $this->assertInstanceof(
+ RedirectTargetUnresolvableException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SemanticDataImportExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SemanticDataImportExceptionTest.php
new file mode 100644
index 00000000..1ae33912
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SemanticDataImportExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\SemanticDataImportException;
+
+/**
+ * @covers \SMW\Exception\SemanticDataImportException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SemanticDataImportExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new SemanticDataImportException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\SemanticDataImportException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SettingNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SettingNotFoundExceptionTest.php
new file mode 100644
index 00000000..5d920793
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SettingNotFoundExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\SettingNotFoundException;
+
+/**
+ * @covers \SMW\Exception\SettingNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SettingNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new SettingNotFoundException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\SettingNotFoundException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/StoreNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/StoreNotFoundExceptionTest.php
new file mode 100644
index 00000000..2c5f3293
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/StoreNotFoundExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\StoreNotFoundException;
+
+/**
+ * @covers \SMW\Exception\StoreNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class StoreNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new StoreNotFoundException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\StoreNotFoundException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SubSemanticDataExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SubSemanticDataExceptionTest.php
new file mode 100644
index 00000000..0d7721fb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exception/SubSemanticDataExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Exception;
+
+use SMW\Exception\SubSemanticDataException;
+
+/**
+ * @covers \SMW\Exception\SubSemanticDataException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SubSemanticDataExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new SubSemanticDataException();
+
+ $this->assertInstanceof(
+ '\SMW\Exception\SubSemanticDataException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ConceptMapperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ConceptMapperTest.php
new file mode 100644
index 00000000..a85346d2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ConceptMapperTest.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace SMW\Tests\Exporter;
+
+use SMW\DIWikiPage;
+use SMW\Exporter\ConceptMapper;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Query\DescriptionFactory;
+
+/**
+ * @covers \SMW\Exporter\ConceptMapper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class ConceptMapperTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionFactory;
+
+ protected function setUp() {
+ $this->descriptionFactory = new DescriptionFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConceptMapper::class,
+ new ConceptMapper()
+ );
+ }
+
+ public function testIsMapperFor() {
+
+ $dataItem = $this->getMockBuilder( '\SMWDIConcept' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ConceptMapper();
+
+ $this->assertTrue(
+ $instance->isMapperFor( $dataItem )
+ );
+ }
+
+ public function testGetExpDataForSingleClassDescription() {
+
+ $instance = new ConceptMapper();
+
+ $exact = false;
+
+ $description = $this->descriptionFactory->newClassDescription(
+ DIWikiPage::newFromText( 'Foo', NS_CATEGORY )
+ );
+
+ $element = new ExpNsResource(
+ 'type',
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+ 'rdf'
+ );
+
+ $result = $instance->getExpDataFromDescription(
+ $description,
+ $exact
+ );
+
+ $this->assertInstanceOf(
+ '\SMWExpData',
+ $result
+ );
+
+ $this->assertEquals(
+ [
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' => $element
+ ],
+ $result->getProperties()
+ );
+ }
+
+ public function testGetExpDataForMultipleClassDescriptions() {
+
+ $instance = new ConceptMapper();
+
+ $exact = false;
+
+ $description = $this->descriptionFactory->newClassDescription(
+ DIWikiPage::newFromText( 'Foo', NS_CATEGORY )
+ );
+
+ $description->addDescription(
+ $this->descriptionFactory->newClassDescription(
+ DIWikiPage::newFromText( 'Bar', NS_CATEGORY )
+ )
+ );
+
+ $elementType = new ExpNsResource(
+ 'type',
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+ 'rdf'
+ );
+
+ $elementUnionOf = new ExpNsResource(
+ 'unionOf',
+ 'http://www.w3.org/2002/07/owl#',
+ 'owl'
+ );
+
+ $result = $instance->getExpDataFromDescription(
+ $description,
+ $exact
+ );
+
+ $this->assertEquals(
+ [
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' => $elementType,
+ 'http://www.w3.org/2002/07/owl#unionOf' => $elementUnionOf
+ ],
+ $result->getProperties()
+ );
+ }
+
+ public function testGetExpDataForThingDescription() {
+
+ $instance = new ConceptMapper();
+
+ $exact = false;
+
+ $description = $this->descriptionFactory->newThingDescription();
+
+ $result = $instance->getExpDataFromDescription(
+ $description,
+ $exact
+ );
+
+ $this->assertFalse(
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/DataItemMatchFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/DataItemMatchFinderTest.php
new file mode 100644
index 00000000..a0091932
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/DataItemMatchFinderTest.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace SMW\Tests\Exporter;
+
+use SMW\DIWikiPage;
+use SMW\Exporter\DataItemMatchFinder;
+
+/**
+ * @covers \SMW\Exporter\DataItemMatchFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DataItemMatchFinderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ DataItemMatchFinder::class,
+ new DataItemMatchFinder( $store )
+ );
+ }
+
+ public function testMatchExpElementOnMatchableWikiNamespaceUri() {
+
+ $dataItem = new DIWikiPage( 'Foo', NS_MAIN, '', 'Bar' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DataItemMatchFinder(
+ $store,
+ 'http://example.org/id/'
+ );
+
+ $expResource = $this->getMockBuilder( '\SMW\Exporter\Element\ExpResource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $expResource->expects( $this->once() )
+ ->method( 'getUri' )
+ ->will( $this->returnValue( 'http://example.org/id/Foo#Bar' ) );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->matchExpElement( $expResource )
+ );
+ }
+
+ public function testMatchExpElementOnMatchableWikiNamespaceUriWithHelpWikiNs() {
+
+ $dataItem = new DIWikiPage( 'Foo', NS_HELP, '', 'Bar' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DataItemMatchFinder(
+ $store,
+ 'http://example.org/id/'
+ );
+
+ $expResource = $this->getMockBuilder( '\SMW\Exporter\Element\ExpResource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $expResource->expects( $this->once() )
+ ->method( 'getUri' )
+ ->will( $this->returnValue( 'http://example.org/id/Help:Foo#Bar' ) );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->matchExpElement( $expResource )
+ );
+ }
+
+ public function testMatchExpElementOnUnmatchableWikiNamespaceUri() {
+
+ $dataItem = new DIWikiPage( 'UNKNOWN', NS_MAIN, '', '' );
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $repositoryConnector = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $repositoryConnector->expects( $this->once() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $repositoryResult ) );
+
+ $store = $this->getMockBuilder( '\SMW\SPARQLStore\SPARQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $repositoryConnector ) );
+
+ $instance = new DataItemMatchFinder(
+ $store,
+ 'http://example.org/id/'
+ );
+
+ $expResource = $this->getMockBuilder( '\SMW\Exporter\Element\ExpResource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $expResource->expects( $this->once() )
+ ->method( 'getUri' )
+ ->will( $this->returnValue( 'http://foo.org/id/Foo#Bar' ) );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->matchExpElement( $expResource )
+ );
+ }
+
+ public function testTryToFindDataItemOnInvalidUri() {
+
+ $store = $this->getMockBuilder( '\SMW\SPARQLStore\SPARQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataItemMatchFinder(
+ $store,
+ 'http://example.org/id/'
+ );
+
+ $expResource = $this->getMockBuilder( '\SMW\Exporter\Element\ExpResource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $expResource->expects( $this->once() )
+ ->method( 'getUri' )
+ ->will( $this->returnValue( '_node1abjt1k9bx17' ) );
+
+ $this->assertNull(
+ $instance->matchExpElement( $expResource )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpElementTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpElementTest.php
new file mode 100644
index 00000000..d3d4d91e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpElementTest.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace SMW\Tests\Exporter\Element;
+
+use SMW\Exporter\Element\ExpElement;
+use SMW\Exporter\Element\ExpLiteral;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\Element\ExpResource;
+
+/**
+ * @covers \SMW\Exporter\Element\ExpElement
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpElementTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = $this->getMockBuilder( '\SMW\Exporter\Element\ExpElement' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\Exporter\Element',
+ $instance
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ '\SMWExpElement',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ */
+ public function testGetDataItem( ExpElement $element ) {
+
+ if ( $element->getDataItem() === null ) {
+ $this->assertNull(
+ $element->getDataItem()
+ );
+ } else {
+ $this->assertInstanceOf(
+ '\SMWDataItem',
+ $element->getDataItem()
+ );
+ }
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ */
+ public function testSerielization( ExpElement $element ) {
+
+ $serialization = ExpElement::newFromSerialization(
+ $element->getSerialization()
+ );
+
+ $this->assertEquals(
+ $element->getDataItem(),
+ $serialization->getDataItem()
+ );
+ }
+
+ public function instanceProvider() {
+
+ $provider = [];
+
+ $provider[] = [ new ExpResource( 'foo' ) ];
+ $provider[] = [ new ExpResource( 'foo', null ) ];
+ $provider[] = [ new ExpResource( 'foo', new \SMWDIBlob( 'bar' ) ) ];
+
+ $provider[] = [ new ExpNsResource( 'foo', 'bar', 'baz' ) ];
+ $provider[] = [ new ExpNsResource( 'foo', 'bar', 'baz', null ) ];
+ $provider[] = [ new ExpNsResource( 'foo', 'bar', 'baz', new \SMWDIBlob( 'bar' ) ) ];
+
+ $provider[] = [ new ExpLiteral( 'foo' ) ];
+ $provider[] = [ new ExpLiteral( 'foo', '' ) ];
+ $provider[] = [ new ExpLiteral( 'foo', 'bar' ) ];
+ $provider[] = [ new ExpLiteral( 'foo', '', '', null ) ];
+ $provider[] = [ new ExpLiteral( 'foo', '', '', new \SMWDIBlob( 'bar' ) ) ];
+ $provider[] = [ new ExpLiteral( 'foo', 'baz', '', new \SMWDIBlob( 'bar' ) ) ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpLiteralTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpLiteralTest.php
new file mode 100644
index 00000000..35ec5df4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpLiteralTest.php
@@ -0,0 +1,272 @@
+<?php
+
+namespace SMW\Tests\Exporter\Element;
+
+use SMW\DIWikiPage;
+use SMW\Exporter\Element\ExpElement;
+use SMW\Exporter\Element\ExpLiteral;
+use SMWDataItem as DataItem;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Exporter\Element\ExpLiteral
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpLiteralTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Exporter\Element\ExpLiteral',
+ new ExpLiteral( '', '', '', null )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ '\SMWExpLiteral',
+ new \SMWExpLiteral( '', '', '', null )
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testAccessToMethods( $lexicalForm, $datatype, $lang, $dataItem ) {
+
+ $instance = new ExpLiteral(
+ $lexicalForm,
+ $datatype,
+ $lang,
+ $dataItem
+ );
+
+ $this->assertEquals(
+ $datatype,
+ $instance->getDatatype()
+ );
+
+ $this->assertEquals(
+ $lang,
+ $instance->getLang()
+ );
+
+ $this->assertEquals(
+ $lexicalForm,
+ $instance->getLexicalForm()
+ );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->getDataItem()
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testSerializiation( $lexicalForm, $datatype, $lang, $dataItem, $expected ) {
+
+ $instance = new ExpLiteral(
+ $lexicalForm,
+ $datatype,
+ $lang,
+ $dataItem
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getSerialization()
+ );
+
+ $this->assertEquals(
+ $instance,
+ ExpElement::newFromSerialization( $instance->getSerialization() )
+ );
+ }
+
+ /**
+ * @dataProvider invalidConstructorProvider
+ */
+ public function testInvalidConstructorThrowsException( $lexicalForm, $datatype, $lang, $dataItem ) {
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+
+ $instance = new ExpLiteral(
+ $lexicalForm,
+ $datatype,
+ $lang,
+ $dataItem
+ );
+ }
+
+ /**
+ * @dataProvider serializationMissingElementProvider
+ */
+ public function testDeserializiationForMissingElementThrowsException( $serialization ) {
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ ExpElement::newFromSerialization(
+ $serialization
+ );
+ }
+
+ public function constructorProvider() {
+
+ #0
+ $provider[] = [
+ '', '', '', null,
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'lexical' => '',
+ 'datatype' => '',
+ 'lang' => '',
+ 'dataitem' => null
+ ]
+ ];
+
+ #1
+ $provider[] = [
+ 'Foo', '', '', null,
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'lexical' => 'Foo',
+ 'datatype' => '',
+ 'lang' => '',
+ 'dataitem' => null
+ ]
+ ];
+
+ #2
+ $provider[] = [
+ 'Foo', 'bar', '', null,
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'lexical' => 'Foo',
+ 'datatype' => 'bar',
+ 'lang' => '',
+ 'dataitem' => null
+ ]
+ ];
+
+ #3
+ $provider[] = [
+ 'Foo', 'bar', '', new DIWikiPage( 'Foo', NS_MAIN ),
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'lexical' => 'Foo',
+ 'datatype' => 'bar',
+ 'lang' => '',
+ 'dataitem' => [
+ 'type' => DataItem::TYPE_WIKIPAGE,
+ 'item' => 'Foo#0##'
+ ]
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ 'Foo', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString', 'en', new DIWikiPage( 'Foo', NS_MAIN ),
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'lexical' => 'Foo',
+ 'datatype' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString',
+ 'lang' => 'en',
+ 'dataitem' => [
+ 'type' => DataItem::TYPE_WIKIPAGE,
+ 'item' => 'Foo#0##'
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function invalidConstructorProvider() {
+
+ #0
+ $provider[] = [
+ [], '', '', null
+ ];
+
+ #1
+ $provider[] = [
+ '', [], '', null
+ ];
+
+ #1
+ $provider[] = [
+ '', '', [], null
+ ];
+
+ return $provider;
+ }
+
+ public function serializationMissingElementProvider() {
+
+ #0
+ $provider[] = [
+ []
+ ];
+
+ #1 Missing dataitem
+ $provider[] = [
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL
+ ]
+ ];
+
+ #2 Bogus type
+ $provider[] = [
+ [
+ 'type' => 'BogusType'
+ ]
+ ];
+
+ #3 Missing uri
+ $provider[] = [
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'dataitem' => null
+ ]
+ ];
+
+ #4 Missing lexical
+ $provider[] = [
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'datatype' => 'foo',
+ 'dataitem' => null
+ ]
+ ];
+
+ #4 Missing datatype
+ $provider[] = [
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'lexical' => 'foo',
+ 'dataitem' => null
+ ]
+ ];
+
+ #5 Missing lang
+ $provider[] = [
+ [
+ 'type' => ExpLiteral::TYPE_LITERAL,
+ 'lexical' => 'foo',
+ 'datatype' => 'foo',
+ 'dataitem' => null
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpNsResourceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpNsResourceTest.php
new file mode 100644
index 00000000..3bac57cb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpNsResourceTest.php
@@ -0,0 +1,259 @@
+<?php
+
+namespace SMW\Tests\Exporter\Element;
+
+use SMW\DIWikiPage;
+use SMW\Exporter\Element\ExpElement;
+use SMW\Exporter\Element\ExpNsResource;
+use SMWDataItem as DataItem;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Exporter\Element\ExpNsResource
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpNsResourceTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Exporter\Element\ExpNsResource',
+ new ExpNsResource( '', '', '', null )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ '\SMWExpNsResource',
+ new \SMWExpNsResource( '', '', '', null )
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testAccessToMethods( $localName, $namespace, $namespaceId, $dataItem ) {
+
+ $instance = new ExpNsResource(
+ $localName,
+ $namespace,
+ $namespaceId,
+ $dataItem
+ );
+
+ $this->assertEquals(
+ $namespaceId . ':' . $localName,
+ $instance->getQName()
+ );
+
+ $this->assertEquals(
+ $namespace . $localName,
+ $instance->getUri()
+ );
+
+ $this->assertEquals(
+ $localName,
+ $instance->getLocalName()
+ );
+
+ $this->assertEquals(
+ $namespace,
+ $instance->getNamespace()
+ );
+
+ $this->assertEquals(
+ $namespaceId,
+ $instance->getNamespaceId()
+ );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->getDataItem()
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testSerializiation( $localName, $namespace, $namespaceId, $dataItem, $expected ) {
+
+ $instance = new ExpNsResource(
+ $localName,
+ $namespace,
+ $namespaceId,
+ $dataItem
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getSerialization()
+ );
+
+ $this->assertEquals(
+ $instance,
+ ExpElement::newFromSerialization( $instance->getSerialization() )
+ );
+ }
+
+ /**
+ * @dataProvider invalidConstructorProvider
+ */
+ public function testInvalidConstructorThrowsException( $localName, $namespace, $namespaceId, $dataItem ) {
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+
+ $instance = new ExpNsResource(
+ $localName,
+ $namespace,
+ $namespaceId,
+ $dataItem
+ );
+ }
+
+ /**
+ * @dataProvider serializationMissingElementProvider
+ */
+ public function testDeserializiationForMissingElementThrowsException( $serialization ) {
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ ExpElement::newFromSerialization(
+ $serialization
+ );
+ }
+
+ public function constructorProvider() {
+
+ #0
+ $provider[] = [
+ '', '', '', null,
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'uri' => '||',
+ 'dataitem' => null
+ ]
+ ];
+
+ #1
+ $provider[] = [
+ 'Foo', '', '', null,
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'uri' => 'Foo||',
+ 'dataitem' => null
+ ]
+ ];
+
+ #2
+ $provider[] = [
+ 'Foo', 'Bar', '', null,
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'uri' => 'Foo|Bar|',
+ 'dataitem' => null
+ ]
+ ];
+
+ #3
+ $provider[] = [
+ 'Foo', 'Bar', 'Fum', null,
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'uri' => 'Foo|Bar|Fum',
+ 'dataitem' => null
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ 'Foo', 'Bar', 'Fum', new DIWikiPage( 'Foo', NS_MAIN ),
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'uri' => 'Foo|Bar|Fum',
+ 'dataitem' => [
+ 'type' => DataItem::TYPE_WIKIPAGE,
+ 'item' => 'Foo#0##'
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function invalidConstructorProvider() {
+
+ #0
+ $provider[] = [
+ [], '', '', null
+ ];
+
+ #1
+ $provider[] = [
+ '', [], '', null
+ ];
+
+ #2
+ $provider[] = [
+ '', '', [], null
+ ];
+
+ return $provider;
+ }
+
+ public function serializationMissingElementProvider() {
+
+ #0
+ $provider[] = [
+ []
+ ];
+
+ #1
+ $provider[] = [
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE
+ ]
+ ];
+
+ #2
+ $provider[] = [
+ [
+ 'type' => 'BogusType'
+ ]
+ ];
+
+ #3
+ $provider[] = [
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'dataitem' => null
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'uri' => '',
+ 'dataitem' => null
+ ]
+ ];
+
+ #5
+ $provider[] = [
+ [
+ 'type' => ExpNsResource::TYPE_NSRESOURCE,
+ 'uri' => '|',
+ 'dataitem' => null
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpResourceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpResourceTest.php
new file mode 100644
index 00000000..885584ac
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/Element/ExpResourceTest.php
@@ -0,0 +1,193 @@
+<?php
+
+namespace SMW\Tests\Exporter\Element;
+
+use SMW\DIWikiPage;
+use SMW\Exporter\Element\ExpElement;
+use SMW\Exporter\Element\ExpResource;
+use SMWDataItem as DataItem;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Exporter\Element\ExpResource
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpResourceTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Exporter\Element\ExpResource',
+ new ExpResource( '', null )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ '\SMWExpResource',
+ new \SMWExpResource( '', null )
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testAccessToMethods( $uri, $dataItem, $isBlankNode ) {
+
+ $instance = new ExpResource(
+ $uri,
+ $dataItem
+ );
+
+ $this->assertEquals(
+ $isBlankNode,
+ $instance->isBlankNode()
+ );
+
+ $this->assertEquals(
+ $uri,
+ $instance->getUri()
+ );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->getDataItem()
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testSerializiation( $uri, $dataItem, $isBlankNode, $expected ) {
+
+ $instance = new ExpResource(
+ $uri,
+ $dataItem
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getSerialization()
+ );
+
+ $this->assertEquals(
+ $instance,
+ ExpElement::newFromSerialization( $instance->getSerialization() )
+ );
+ }
+
+ /**
+ * @dataProvider invalidConstructorProvider
+ */
+ public function testInvalidConstructorThrowsException( $uri, $dataItem ) {
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+
+ $instance = new ExpResource(
+ $uri,
+ $dataItem
+ );
+ }
+
+ /**
+ * @dataProvider serializationMissingElementProvider
+ */
+ public function testDeserializiationForMissingElementThrowsException( $serialization ) {
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ ExpElement::newFromSerialization(
+ $serialization
+ );
+ }
+
+ public function constructorProvider() {
+
+ #0
+ $provider[] = [
+ '', null,
+ true,
+ [
+ 'type' => ExpResource::TYPE_RESOURCE,
+ 'uri' => '',
+ 'dataitem' => null
+ ]
+ ];
+
+ #1
+ $provider[] = [
+ 'Foo', null,
+ false,
+ [
+ 'type' => ExpResource::TYPE_RESOURCE,
+ 'uri' => 'Foo',
+ 'dataitem' => null
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ 'Foo', new DIWikiPage( 'Foo', NS_MAIN ),
+ false,
+ [
+ 'type' => ExpResource::TYPE_RESOURCE,
+ 'uri' => 'Foo',
+ 'dataitem' => [
+ 'type' => DataItem::TYPE_WIKIPAGE,
+ 'item' => 'Foo#0##'
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function invalidConstructorProvider() {
+
+ #0
+ $provider[] = [
+ [], null
+ ];
+
+ return $provider;
+ }
+
+ public function serializationMissingElementProvider() {
+
+ #0
+ $provider[] = [
+ []
+ ];
+
+ #1 Missing dataitem
+ $provider[] = [
+ [
+ 'type' => ExpResource::TYPE_RESOURCE
+ ]
+ ];
+
+ #2 Bogus type
+ $provider[] = [
+ [
+ 'type' => 'BogusType'
+ ]
+ ];
+
+ #3 Missing uri
+ $provider[] = [
+ [
+ 'type' => ExpResource::TYPE_RESOURCE,
+ 'dataitem' => null
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ElementFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ElementFactoryTest.php
new file mode 100644
index 00000000..8dcadf6f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ElementFactoryTest.php
@@ -0,0 +1,136 @@
+<?php
+
+namespace SMW\Tests\Exporter;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\ElementFactory;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Exporter\ElementFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ElementFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ /**
+ * @dataProvider supportedDataItemProvider
+ */
+ public function testNewFromDataItemForSupportedTypes( $dataItem ) {
+
+ $instance = new ElementFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Exporter\Element',
+ $instance->newFromDataItem( $dataItem )
+ );
+ }
+
+ /**
+ * @dataProvider unsupportedDataItemProvider
+ */
+ public function testUnsupportedDataItemTypes( $dataItem ) {
+
+ $instance = new ElementFactory();
+
+ $this->assertNull(
+ $instance->newFromDataItem( $dataItem )
+ );
+ }
+
+ public function testNotSupportedEncoderResultThrowsException() {
+
+ $dataItemFactory = new DataItemFactory();
+ $instance = new ElementFactory();
+
+ $instance->registerDataItemMapper( \SMWDataItem::TYPE_BLOB, function( $datatem ) {
+ return new \stdclass;
+ } );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->newFromDataItem( $dataItemFactory->newDIBlob( 'foo' ) );
+ }
+
+ public function supportedDataItemProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ #0
+ $provider[] = [
+ $dataItemFactory->newDINumber( 42 )
+ ];
+
+ #1
+ $provider[] = [
+ $dataItemFactory->newDIBlob( 'Test' )
+ ];
+
+ #2
+ $provider[] = [
+ $dataItemFactory->newDIBoolean( true )
+ ];
+
+ #3
+ $provider[] = [
+ $dataItemFactory->newDIUri( 'http', '//example.org', '', '' )
+ ];
+
+ #4
+ $provider[] = [
+ $dataItemFactory->newDITime( 1, '1970' )
+ ];
+
+ #5
+ $provider[] = [
+ $dataItemFactory->newDIContainer( new \SMWContainerSemanticData( $dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN ) ) )
+ ];
+
+ #6
+ $provider[] = [
+ $dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN )
+ ];
+
+ #7
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' )
+ ];
+
+ #8
+ $provider[] = [
+ $dataItemFactory->newDIConcept( 'Foo', '', '', '', '' )
+ ];
+
+ return $provider;
+ }
+
+ public function unsupportedDataItemProvider() {
+
+ $dataItem = $this->getMockBuilder( '\SMWDataItem' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ '__toString' ] )
+ ->getMockForAbstractClass();
+
+ $dataItem->expects( $this->any() )
+ ->method( '__toString' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ #0
+ $provider[] = [
+ $dataItem
+ ];
+
+ #1
+ $provider[] = [
+ new \SMWDIGeoCoord( [ 'lat' => 52, 'lon' => 1 ] )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/EscaperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/EscaperTest.php
new file mode 100644
index 00000000..555b3534
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/EscaperTest.php
@@ -0,0 +1,160 @@
+<?php
+
+namespace SMW\Tests\Exporter;
+
+use SMW\DIWikiPage;
+use SMW\Exporter\Escaper;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Exporter\Escaper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class EscaperTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->addConfiguration( 'smwgExportResourcesAsIri', false );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider encodePageProvider
+ */
+ public function testEncodePage( $page, $expected ) {
+
+ $this->assertSame(
+ $expected,
+ Escaper::encodePage( $page )
+ );
+ }
+
+
+ /**
+ * @dataProvider encodeUriProvider
+ */
+ public function testEncodeUri( $uri, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ Escaper::encodeUri( $uri )
+ );
+
+ $this->assertEquals(
+ $uri,
+ Escaper::decodeUri( Escaper::encodeUri( $uri ) )
+ );
+ }
+
+ /**
+ * @dataProvider decodeUriProvider
+ */
+ public function testDecodeUri( $uri, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ Escaper::decodeUri( $uri )
+ );
+
+ $this->assertEquals(
+ $uri,
+ Escaper::encodeUri( Escaper::decodeUri( $uri ) )
+ );
+ }
+
+ public function encodeUriProvider() {
+
+ $provider[] = [
+ 'Foo:"&+!%#',
+ 'Foo-3A-22-26-2B-21-25-23'
+ ];
+
+ $provider[] = [
+ "Foo'-'",
+ 'Foo-27-2D-27'
+ ];
+ return $provider;
+ }
+
+ public function decodeUriProvider() {
+
+ $provider[] = [
+ 'Foo-3A-22-26-2B-21-25-23',
+ 'Foo:"&+!%#'
+ ];
+
+ $provider[] = [
+ 'Foo-27-2D-27',
+ "Foo'-'"
+ ];
+
+ return $provider;
+ }
+
+ public function encodePageProvider() {
+
+ #0
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN, '', '' )
+ , 'Foo'
+ ];
+
+ #1
+ $provider[] = [
+ new DIWikiPage( 'Foo_bar', NS_MAIN, '', '' ),
+ 'Foo_bar'
+ ];
+
+ #2
+ $provider[] = [
+ new DIWikiPage( 'Foo%bar', NS_MAIN, '', '' ),
+ 'Foo-25bar'
+ ];
+
+ #3 / #759
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN, 'bar', '' ),
+ 'bar-3AFoo'
+ ];
+
+ #4 / #759
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN, 'bar', 'yuu' ),
+ 'bar-3AFoo'
+ ];
+
+ #5
+ $provider[] = [
+ new DIWikiPage( 'Fooºr', NS_MAIN, '', '' ),
+ 'Foo-C2-BAr'
+ ];
+
+ #6
+ $provider[] = [
+ new DIWikiPage( 'Fooºr', SMW_NS_PROPERTY, '', '' ),
+ 'Property-3AFoo-C2-BAr'
+ ];
+
+ #7
+ $provider[] = [
+ new DIWikiPage( 'Fooºr', NS_CATEGORY, '', '' ),
+ 'Category-3AFoo-C2-BAr'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ExpResourceMapperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ExpResourceMapperTest.php
new file mode 100644
index 00000000..c1eeb876
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ExpResourceMapperTest.php
@@ -0,0 +1,266 @@
+<?php
+
+namespace SMW\Tests\Exporter;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Exporter\Element;
+use SMW\Exporter\Escaper;
+use SMW\Exporter\ExpResourceMapper;
+use SMW\InMemoryPoolCache;
+
+/**
+ * @covers \SMW\Exporter\ExpResourceMapper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpResourceMapperTest extends \PHPUnit_Framework_TestCase {
+
+ private $inMemoryPoolCache;
+
+ protected function setUp() {
+ $this->inMemoryPoolCache = InMemoryPoolCache::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->inMemoryPoolCache->clear();
+ }
+
+ public function testInvalidateCache() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $poolCache = $this->inMemoryPoolCache->getPoolCacheById( 'exporter.expresource.mapper' );
+
+ $poolCache->save(
+ $subject->getHash(),
+ true
+ );
+
+ $poolCache->save(
+ $subject->getHash() . ExpResourceMapper::AUX_MARKER,
+ true
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new ExpResourceMapper(
+ $store
+ );
+
+ $instance->invalidateCache(
+ $subject
+ );
+
+ $this->assertFalse(
+ $poolCache->contains( $subject->getHash() )
+ );
+ }
+
+ public function testMapPropertyToResourceElement() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new ExpResourceMapper(
+ $store
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Exporter\Element\ExpNsResource',
+ $instance->mapPropertyToResourceElement( new DIProperty( 'Foo' ) )
+ );
+ }
+
+ /**
+ * @dataProvider diWikiPageProvider
+ */
+ public function testMapWikiPageToResourceElement( $dataItem, $modifier, $expected ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new ExpResourceMapper(
+ $store
+ );
+
+ $resource = $instance->mapWikiPageToResourceElement( $dataItem, $modifier );
+
+ $this->assertSame(
+ $expected,
+ $resource->getSerialization()
+ );
+ }
+
+ /**
+ * @dataProvider importDataProvider
+ */
+ public function testMapWikiPageToResourceElementForImportMatch( $dataItem, $expected ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will(
+ $this->returnValue( [ new \SMWDIBlob( 'foo:bar:fom:fuz' ) ] ) );
+
+ $instance = new ExpResourceMapper(
+ $store
+ );
+
+ $resource = $instance->mapWikiPageToResourceElement(
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $resource->isImported()
+ );
+
+ $this->assertSame(
+ $expected,
+ $resource->getSerialization()
+ );
+ }
+
+ public function diWikiPageProvider() {
+
+ // Constant
+ $wiki = \SMWExporter::getInstance()->getNamespaceUri( 'wiki' );
+ $property = \SMWExporter::getInstance()->getNamespaceUri( 'property' );
+
+ #0
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN, '', '' ),
+ '',
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "Foo|{$wiki}|wiki",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#0##' ]
+ ]
+ ];
+
+ #1
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN, 'bar', '' ),
+ '',
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "bar-3AFoo|{$wiki}|wiki",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#0#bar#' ]
+ ]
+ ];
+
+ #2
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN, 'bar', '1234' ),
+ '',
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "bar-3AFoo-231234|{$wiki}|wiki",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#0#bar#1234' ]
+ ]
+ ];
+
+ #3 Extra modififer doesn't not alter the object when a subobject is used
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN, 'bar', '1234' ),
+ 'abc',
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "bar-3AFoo-231234|{$wiki}|wiki",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#0#bar#1234' ]
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY, '', '' ),
+ '',
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "Foo|{$property}|property",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#102##' ]
+ ]
+ ];
+
+ #5
+ $provider[] = [
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY, '', '' ),
+ true,
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "Foo-23aux|{$property}|property",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#102##' ]
+ ]
+ ];
+
+ #6
+ $name = Escaper::encodePage(
+ new DIWikiPage( '-Foo', SMW_NS_PROPERTY, '', '' )
+ );
+
+ $provider[] = [
+ new DIWikiPage( '-Foo', SMW_NS_PROPERTY, '', '' ),
+ true,
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "$name-23aux|{$wiki}|wiki",
+ 'dataitem' => [ 'type' => 9, 'item' => '-Foo#102##' ]
+ ]
+ ];
+
+ #7
+ $provider[] = [
+ new DIWikiPage( 'Foo/Bar', SMW_NS_PROPERTY, '', '' ),
+ '',
+ [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "Property-3AFoo-2FBar|{$wiki}|wiki",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo/Bar#102##' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function importDataProvider() {
+
+ // || is not the result we normally would expect but mocking the
+ // dataValueFactory at this point is not worth the hassle therefore
+ // we live with || output
+ $expected = [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "||",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#102##' ]
+ ];
+
+ $provider[] = [
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY, '', '' ),
+ $expected
+ ];
+
+ $expected = [
+ 'type' => Element::TYPE_NSRESOURCE,
+ 'uri' => "||",
+ 'dataitem' => [ 'type' => 9, 'item' => 'Foo#14##' ]
+ ];
+
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_CATEGORY, '', '' ),
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/AuxiliaryPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/AuxiliaryPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..45f91d3d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/AuxiliaryPropertyValueResourceBuilderTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\AuxiliaryPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\AuxiliaryPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class AuxiliaryPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ AuxiliaryPropertyValueResourceBuilder::class,
+ new AuxiliaryPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonImpoProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new AuxiliaryPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForSelectedAuxiliaryProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_dat' );
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new AuxiliaryPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ConceptPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ConceptPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..2a69db33
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ConceptPropertyValueResourceBuilderTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\ConceptPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\ConceptPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ConceptPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ ConceptPropertyValueResourceBuilder::class,
+ new ConceptPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonConcProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new ConceptPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForConcProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_CONC' );
+ $dataItem = $this->dataItemFactory->newDIConcept( 'Foo' );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new ConceptPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/DispatchingResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/DispatchingResourceBuilderTest.php
new file mode 100644
index 00000000..27156d12
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/DispatchingResourceBuilderTest.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\ResourceBuilder;
+use SMW\Exporter\ResourceBuilders\DispatchingResourceBuilder;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\DispatchingResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DispatchingResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ DispatchingResourceBuilder::class,
+ new DispatchingResourceBuilder()
+ );
+ }
+
+ public function testIsResourceBuilderForValidMatch() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $resourceBuilder = $this->getMockBuilder( ResourceBuilder::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resourceBuilder->expects( $this->once() )
+ ->method( 'isResourceBuilderFor' )
+ ->with( $this->equalTo( $property ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new DispatchingResourceBuilder();
+ $instance->addResourceBuilder( $resourceBuilder );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testIsResourceBuilderForInvalidMatch() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new DispatchingResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueOnValidMatchedResourceBuilder() {
+
+ $expData = $this->getMockBuilder( '\SMWExpData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $dataItem = $this->dataItemFactory->newDIBlob( 'Bar' );
+
+ $resourceBuilder = $this->getMockBuilder( ResourceBuilder::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resourceBuilder->expects( $this->once() )
+ ->method( 'isResourceBuilderFor' )
+ ->will( $this->returnValue( true ) );
+
+ $resourceBuilder->expects( $this->once() )
+ ->method( 'addResourceValue' );
+
+ $instance = new DispatchingResourceBuilder();
+ $instance->addResourceBuilder( $resourceBuilder );
+
+ $instance->addResourceValue( $expData, $property, $dataItem );
+ }
+
+ public function testAddResourceValueOnDefaultResourceBuilderWhenOthersCannotMatch() {
+
+ $expData = $this->getMockBuilder( '\SMWExpData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $dataItem = $this->dataItemFactory->newDIBlob( 'Bar' );
+
+ $resourceBuilder = $this->getMockBuilder( ResourceBuilder::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resourceBuilder->expects( $this->once() )
+ ->method( 'isResourceBuilderFor' )
+ ->will( $this->returnValue( false ) );
+
+ $defaultResourceBuilder = $this->getMockBuilder( ResourceBuilder::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $defaultResourceBuilder->expects( $this->once() )
+ ->method( 'addResourceValue' );
+
+ $instance = new DispatchingResourceBuilder();
+
+ $instance->addResourceBuilder( $resourceBuilder );
+ $instance->addDefaultResourceBuilder( $defaultResourceBuilder );
+
+ $instance->addResourceValue( $expData, $property, $dataItem );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ExternalIdentifierPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ExternalIdentifierPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..754bab14
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ExternalIdentifierPropertyValueResourceBuilderTest.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\ExternalIdentifierPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\ExternalIdentifierPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ExternalIdentifierPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ ExternalIdentifierPropertyValueResourceBuilder::class,
+ new ExternalIdentifierPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonExternalIdentifierTypedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new ExternalIdentifierPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForValidProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_eid' );
+
+ $dataItem = $this->dataItemFactory->newDIBlob( 'Bar' );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new ExternalIdentifierPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ImportFromPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ImportFromPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..a37c2612
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/ImportFromPropertyValueResourceBuilderTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\ImportFromPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\ImportFromPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ImportFromPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ ImportFromPropertyValueResourceBuilder::class,
+ new ImportFromPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonImpoProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new ImportFromPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForImpoProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_IMPO' );
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', $this->dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN ) )
+ );
+
+ $instance = new ImportFromPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/KeywordPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/KeywordPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..048212b3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/KeywordPropertyValueResourceBuilderTest.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\KeywordPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\KeywordPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class KeywordPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ KeywordPropertyValueResourceBuilder::class,
+ new KeywordPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonExternalIdentifierTypedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new KeywordPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForValidProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_keyw' );
+
+ $dataItem = $this->dataItemFactory->newDIBlob( 'Bar' );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new KeywordPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/MonolingualTextPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/MonolingualTextPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..36753052
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/MonolingualTextPropertyValueResourceBuilderTest.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\MonolingualTextPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\MonolingualTextPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class MonolingualTextPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $dataValueFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ MonolingualTextPropertyValueResourceBuilder::class,
+ new MonolingualTextPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonExternalIdentifierTypedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new MonolingualTextPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForValidProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_mlt_rec' );
+
+ $monolingualTextValue = $this->dataValueFactory->newDataValueByProperty(
+ $property,
+ 'Bar@en'
+ );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new MonolingualTextPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $monolingualTextValue->getDataItem()
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PredefinedPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PredefinedPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..2d42d338
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PredefinedPropertyValueResourceBuilderTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\PredefinedPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\PredefinedPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PredefinedPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ PredefinedPropertyValueResourceBuilder::class,
+ new PredefinedPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForUserDefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new PredefinedPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForPredefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_boo' );
+ $dataItem = $this->dataItemFactory->newDIBoolean( true );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new PredefinedPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PreferredPropertyLabelResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PreferredPropertyLabelResourceBuilderTest.php
new file mode 100644
index 00000000..7c0e5934
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PreferredPropertyLabelResourceBuilderTest.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\PreferredPropertyLabelResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\PreferredPropertyLabelResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PreferredPropertyLabelResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $dataValueFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ PreferredPropertyLabelResourceBuilder::class,
+ new PreferredPropertyLabelResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonPreferredPropertyLabelProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new PreferredPropertyLabelResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForValidProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_PPLB' );
+
+ $monolingualTextValue = $this->dataValueFactory->newDataValueByProperty(
+ $property,
+ 'Bar@en'
+ );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new PreferredPropertyLabelResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $monolingualTextValue->getDataItem()
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyDescriptionValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyDescriptionValueResourceBuilderTest.php
new file mode 100644
index 00000000..2cbd9275
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyDescriptionValueResourceBuilderTest.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\PropertyDescriptionValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\PropertyDescriptionValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyDescriptionValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $dataValueFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ PropertyDescriptionValueResourceBuilder::class,
+ new PropertyDescriptionValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForPropertyDescription() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new PropertyDescriptionValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForPropertyDescription() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_PDESC' );
+
+ $monolingualTextValue = $this->dataValueFactory->newDataValueByProperty(
+ $property,
+ 'Some description@en'
+ );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new PropertyDescriptionValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $monolingualTextValue->getDataItem()
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..8fc83d3b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/PropertyValueResourceBuilderTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\PropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\PropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ PropertyValueResourceBuilder::class,
+ new PropertyValueResourceBuilder()
+ );
+ }
+
+ public function testAddResourceValue() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new PropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/RedirectPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/RedirectPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..9e01f6e4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/RedirectPropertyValueResourceBuilderTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\RedirectPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\RedirectPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class RedirectPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ RedirectPropertyValueResourceBuilder::class,
+ new RedirectPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonRediProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new RedirectPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForRediPropert() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_REDI' );
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new RedirectPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/SortPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/SortPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..41c27c34
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/SortPropertyValueResourceBuilderTest.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\SortPropertyValueResourceBuilder;
+use SMW\Serializers\ExpDataSerializer;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\SortPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SortPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $testEnvironment;
+ private $expDataSerializer;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+ $this->expDataSerializer = new ExpDataSerializer();
+
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ SortPropertyValueResourceBuilder::class,
+ new SortPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNon_SKEYProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new SortPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testIsResourceBuilderFor_SKEYProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_SKEY' );
+
+ $instance = new SortPropertyValueResourceBuilder();
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueFor_SKEYProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_SKEY' );
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new SortPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $res = json_encode( $this->expDataSerializer->serialize( $expData ) );
+
+ $this->assertNotContains(
+ 'sort|http:\/\/semantic-mediawiki.org\/swivt\/1.0#|swivt',
+ $res
+ );
+ }
+
+ public function testAddResourceValueFor_SKEYPropertyWithEnabledCollationField() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_SKEY' );
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new SortPropertyValueResourceBuilder();
+ $instance->enabledCollationField( true );
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $res = json_encode( $this->expDataSerializer->serialize( $expData ) );
+
+ $this->assertContains(
+ 'sort|http:\/\/semantic-mediawiki.org\/swivt\/1.0#|swivt',
+ $res
+ );
+
+ $this->assertContains(
+ 'http:\/\/www.w3.org\/2001\/XMLSchema#string',
+ $res
+ );
+ }
+
+ public function testAddResourceValueFor_SKEYPropertyWithEnabledCollationFieldOnBlobItem() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_SKEY' );
+ $dataItem = $this->dataItemFactory->newDIBlob( 'Bar' );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', '', '', null )
+ );
+
+ $instance = new SortPropertyValueResourceBuilder();
+ $instance->enabledCollationField( true );
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $dataItem
+ );
+
+ $res = json_encode( $this->expDataSerializer->serialize( $expData ) );
+
+ $this->assertContains(
+ 'sort|http:\/\/semantic-mediawiki.org\/swivt\/1.0#|swivt',
+ $res
+ );
+
+ $this->assertContains(
+ 'http:\/\/www.w3.org\/2001\/XMLSchema#string',
+ $res
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/UniquenessConstraintPropertyValueResourceBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/UniquenessConstraintPropertyValueResourceBuilderTest.php
new file mode 100644
index 00000000..a5f0e1be
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/ResourceBuilders/UniquenessConstraintPropertyValueResourceBuilderTest.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\Exporter\ResourceBuilders;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\ResourceBuilders\UniquenessConstraintPropertyValueResourceBuilder;
+use SMW\Tests\TestEnvironment;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMW\Exporter\ResourceBuilders\UniquenessConstraintPropertyValueResourceBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class UniquenessConstraintPropertyValueResourceBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $dataValueFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->resetPoolCacheById( \SMWExporter::POOLCACHE_ID );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ UniquenessConstraintPropertyValueResourceBuilder::class,
+ new UniquenessConstraintPropertyValueResourceBuilder()
+ );
+ }
+
+ public function testIsNotResourceBuilderForNonUniquenessConstraintProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new UniquenessConstraintPropertyValueResourceBuilder();
+
+ $this->assertFalse(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+ public function testAddResourceValueForValidProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_PVUC' );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foobar', 'Bar', 'Mo', null )
+ );
+
+ $instance = new UniquenessConstraintPropertyValueResourceBuilder();
+
+ $instance->addResourceValue(
+ $expData,
+ $property,
+ $this->dataItemFactory->newDIBoolean( true )
+ );
+
+ $this->assertTrue(
+ $instance->isResourceBuilderFor( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/XsdValueMapperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/XsdValueMapperTest.php
new file mode 100644
index 00000000..ced69e1a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Exporter/XsdValueMapperTest.php
@@ -0,0 +1,162 @@
+<?php
+
+namespace SMW\Tests\Exporter;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Exporter\XsdValueMapper;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Exporter\XsdValueMapper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class XsdValueMapperTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ /**
+ * @dataProvider supportedDataItemProvider
+ */
+ public function testMatchSupportedTypes( $dataItem, $xsdValue, $xsdType ) {
+
+ $instance = new XsdValueMapper();
+
+ $instance->map( $dataItem );
+
+ $this->assertEquals(
+ $xsdValue,
+ $instance->getXsdValue()
+ );
+
+ $this->assertContains(
+ $xsdType,
+ $instance->getXsdType()
+ );
+ }
+
+ /**
+ * @dataProvider unsupportedDataItemProvider
+ */
+ public function testTryToMatchUnsupportedTypeThrowsException( $dataItem ) {
+
+ $instance = new XsdValueMapper();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->map( $dataItem );
+ }
+
+ public function supportedDataItemProvider() {
+
+ #0
+ $provider[] = [
+ new \SMWDINumber( 42 ),
+ '42',
+ 'double'
+ ];
+
+ #1
+ $provider[] = [
+ new \SMWDIBlob( 'Test' ),
+ 'Test',
+ 'string'
+ ];
+
+ #2
+ $provider[] = [
+ new \SMWDIBoolean( true ),
+ 'true',
+ 'boolean'
+ ];
+
+ #3
+ $provider[] = [
+ new \SMWDITime( 1, '1970' ),
+ '1970',
+ 'gYear'
+ ];
+
+ #4
+ $provider[] = [
+ new \SMWDITime( 1, '1970', '12' ),
+ '1970-12',
+ 'gYearMonth'
+ ];
+
+ #5
+ $provider[] = [
+ new \SMWDITime( 1, '1970', '12', '31' ),
+ '1970-12-31Z',
+ 'date'
+ ];
+
+ #6
+ $provider[] = [
+ new \SMWDITime( 1, '1970', '12', '31', '12' ),
+ '1970-12-31T12:00:00Z',
+ 'dateTime'
+ ];
+
+ return $provider;
+ }
+
+ public function unsupportedDataItemProvider() {
+
+ $dataItem = $this->getMockBuilder( '\SMWDataItem' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ '__toString' ] )
+ ->getMockForAbstractClass();
+
+ $dataItem->expects( $this->any() )
+ ->method( '__toString' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ #0
+ $provider[] = [
+ $dataItem
+ ];
+
+ #1
+ $provider[] = [
+ new \SMWDIGeoCoord( [ 'lat' => 52, 'lon' => 1 ] )
+ ];
+
+ #2
+ $provider[] = [
+ new \SMWDIConcept( 'Foo', '', '', '', '' )
+ ];
+
+ #3
+ $provider[] = [
+ new \SMWDIUri( 'http', '//example.org', '', '' )
+ ];
+
+ #4
+ $provider[] = [
+ new \SMWDIContainer( new \SMWContainerSemanticData( new DIWikiPage( 'Foo', NS_MAIN ) ) )
+ ];
+
+ #5
+ $provider[] = [
+ new DIWikiPage( 'Foo', NS_MAIN )
+ ];
+
+ #6
+ $provider[] = [
+ new DIProperty( 'Foo' )
+ ];
+
+ #7 Not a gregorian calendar model
+ $provider[] = [
+ new \SMWDITime( 2, '1970' )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/CachedFactboxTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/CachedFactboxTest.php
new file mode 100644
index 00000000..12dce804
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/CachedFactboxTest.php
@@ -0,0 +1,535 @@
+<?php
+
+namespace SMW\Tests\Factbox;
+
+use Language;
+use ParserOutput;
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Factbox\CachedFactbox;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockTitle;
+
+/**
+ * @covers \SMW\Factbox\CachedFactbox
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class CachedFactboxTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $memoryCache;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->memoryCache = ApplicationFactory::getInstance()->newCacheFactory()->newFixedInMemoryCache();
+
+ $this->testEnvironment->withConfiguration(
+ [
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE | SMW_FACTBOX_PURGE_REFRESH | SMW_FACTBOX_DISPLAY_SUBOBJECT,
+ 'smwgMainCacheType' => 'hash'
+ ]
+ );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Factbox\CachedFactbox',
+ new CachedFactbox( $cache, new \stdClass )
+ );
+ }
+
+ /**
+ * @dataProvider outputDataProvider
+ */
+ public function testProcessAndRetrieveContent( $parameters, $expected ) {
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgNamespacesWithSemanticLinks',
+ $parameters['smwgNamespacesWithSemanticLinks']
+ );
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgShowFactbox',
+ $parameters['smwgShowFactbox']
+ );
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgFactboxFeatures',
+ $parameters['smwgFactboxFeatures']
+ );
+
+ $this->testEnvironment->registerObject( 'Store', $parameters['store'] );
+
+ $outputPage = $parameters['outputPage'];
+
+ $instance = new CachedFactbox( $this->memoryCache );
+ $instance->isEnabled( true );
+ $instance->setFeatureSet( $parameters['smwgFactboxFeatures'] );
+
+ $this->assertEmpty(
+ $instance->retrieveContent( $outputPage )
+ );
+
+ $instance->prepareFactboxContent(
+ $outputPage,
+ $parameters['language'],
+ $parameters['parserOutput']
+ );
+
+ $result = $outputPage->mSMWFactboxText;
+
+ $this->assertPreProcess(
+ $expected,
+ $result,
+ $outputPage,
+ $instance
+ );
+
+ // Re-run on the same instance
+ $instance->prepareFactboxContent(
+ $outputPage,
+ $parameters['language'],
+ $parameters['parserOutput']
+ );
+
+ $this->assertPostProcess(
+ $expected,
+ $result,
+ $outputPage,
+ $instance
+ );
+ }
+
+ public function assertPreProcess( $expected, $result, $outputPage, $instance ) {
+
+ if ( $expected['text'] ) {
+
+ $this->assertContains(
+ $expected['text'],
+ $result,
+ 'Asserts that content was altered as expected'
+ );
+
+ // Deliberately clear the outputPage property to force
+ // content to be retrieved from the cache
+ unset( $outputPage->mSMWFactboxText );
+
+ $this->assertTrue(
+ $result === $instance->retrieveContent( $outputPage ),
+ 'Asserts that cached content was retrievable'
+ );
+
+ } else {
+
+ $this->assertNull(
+ $result,
+ 'Asserts that the result is null'
+ );
+ }
+ }
+
+ public function assertPostProcess( $expected, $result, $outputPage, $instance ) {
+
+ $this->assertEquals(
+ $result,
+ $instance->retrieveContent( $outputPage ),
+ 'Asserts that content is being fetched from cache'
+ );
+
+ $this->assertTrue(
+ $result === $outputPage->mSMWFactboxText,
+ 'Asserts that content from the outputpage property and retrieveContent() is equal'
+ );
+
+ if ( $expected['text'] ) {
+
+ $this->assertTrue(
+ $instance->isCached(),
+ 'Asserts that isCached() returns true'
+ );
+
+ } else {
+
+ $this->assertFalse(
+ $instance->isCached(),
+ 'Asserts that isCached() returns false'
+ );
+ }
+ }
+
+ public function outputDataProvider() {
+
+ $language = Language::factory( 'en' );
+
+ $title = MockTitle::buildMockForMainNamespace( __METHOD__ . 'mock-subject' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $subject = DIWikiPage::newFromTitle( $title );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'hasVisibleProperties' )
+ ->will( $this->returnValue( true ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromTitle( $title ) ] ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [ new DIProperty( __METHOD__ . 'property' ) ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ #0 Factbox build, being visible
+ $title = MockTitle::buildMock( __METHOD__ . 'title-being-visible' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 10001 ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 10001 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE | SMW_FACTBOX_PURGE_REFRESH | SMW_FACTBOX_DISPLAY_SUBOBJECT,
+ 'smwgShowFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'outputPage' => $outputPage,
+ 'store' => $store,
+ 'language' => $language,
+ 'parserOutput' => $this->makeParserOutput( $semanticData )
+ ],
+ [
+ 'text' => $subject->getDBKey()
+ ]
+ ];
+
+ #1 Factbox build, being visible, using WebRequest oldid
+ $title = MockTitle::buildMock( __METHOD__ . 'title-with-oldid' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 10002 ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 10002 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $context = new \RequestContext( );
+ $context->setRequest( new \FauxRequest( [ 'oldid' => 9001 ], true ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $context ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE | SMW_FACTBOX_PURGE_REFRESH | SMW_FACTBOX_DISPLAY_SUBOBJECT,
+ 'smwgShowFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'outputPage' => $outputPage,
+ 'store' => $store,
+ 'language' => $language,
+ 'parserOutput' => $this->makeParserOutput( $semanticData )
+ ],
+ [
+ 'text' => $subject->getDBKey()
+ ]
+ ];
+
+ #2 Factbox is expected not to be visible
+ $title = MockTitle::buildMock( __METHOD__ . 'title-ns-disabled' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 10003 ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 10003 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => false ],
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE | SMW_FACTBOX_PURGE_REFRESH | SMW_FACTBOX_DISPLAY_SUBOBJECT,
+ 'smwgShowFactbox' => SMW_FACTBOX_HIDDEN,
+ 'outputPage' => $outputPage,
+ 'store' => $store,
+ 'language' => $language,
+ 'parserOutput' => $this->makeParserOutput( $semanticData )
+ ],
+ [
+ 'text' => null
+ ]
+ ];
+
+ #3 No semantic data
+ $title = MockTitle::buildMock( __METHOD__ . 'title-empty-semanticdata' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 10004 ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 10004 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'isEmpty' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE | SMW_FACTBOX_PURGE_REFRESH | SMW_FACTBOX_DISPLAY_SUBOBJECT,
+ 'smwgShowFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'outputPage' => $outputPage,
+ 'store' => $store,
+ 'language' => $language,
+ 'parserOutput' => $this->makeParserOutput( null ),
+ ],
+ [
+ 'text' => null
+ ]
+ ];
+
+ // #4 SpecialPage
+ $title = MockTitle::buildMock( __METHOD__ . 'title-specialpage' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE | SMW_FACTBOX_PURGE_REFRESH | SMW_FACTBOX_DISPLAY_SUBOBJECT,
+ 'smwgShowFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'outputPage' => $outputPage,
+ 'store' => $store,
+ 'language' => $language,
+ 'parserOutput' => $this->makeParserOutput( null ),
+ ],
+ [
+ 'text' => ''
+ ]
+ ];
+
+ // #5 does not exist
+ $title = MockTitle::buildMock( __METHOD__ . 'title-not-exists' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( false ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE | SMW_FACTBOX_PURGE_REFRESH | SMW_FACTBOX_DISPLAY_SUBOBJECT,
+ 'smwgShowFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'outputPage' => $outputPage,
+ 'store' => $store,
+ 'language' => $language,
+ 'parserOutput' => $this->makeParserOutput( null ),
+ ],
+ [
+ 'text' => ''
+ ]
+ ];
+
+ return $provider;
+ }
+
+ protected function makeParserOutput( $semanticData ) {
+
+ $parserOutput = new ParserOutput();
+
+ if ( method_exists( $parserOutput, 'setExtensionData' ) ) {
+ $parserOutput->setExtensionData( 'smwdata', $semanticData );
+ } else {
+ $parserOutput->mSMWData = $semanticData;
+ }
+
+ return $parserOutput;
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxFactoryTest.php
new file mode 100644
index 00000000..b4fe99ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxFactoryTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Factbox;
+
+use SMW\Factbox\FactboxFactory;
+use Title;
+
+/**
+ * @covers \SMW\Factbox\FactboxFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class FactboxFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Factbox\FactboxFactory',
+ new FactboxFactory()
+ );
+ }
+
+ public function testCanConstructCachedFactbox() {
+
+ $instance = new FactboxFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Factbox\CachedFactbox',
+ $instance->newCachedFactbox()
+ );
+ }
+
+ public function testCanConstructFactbox() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new FactboxFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Factbox\Factbox',
+ $instance->newFactbox( $title, $parserOutput )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxMagicWordsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxMagicWordsTest.php
new file mode 100644
index 00000000..6df246fb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxMagicWordsTest.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace SMW\Tests\Factbox;
+
+use ParserOutput;
+use ReflectionClass;
+use SMW\ApplicationFactory;
+use SMW\Factbox\Factbox;
+use SMW\ParserData;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\Factbox\Factbox
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class FactboxMagicWordsTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider textDataProvider
+ */
+ public function testMagicWordsFromParserOutputExtension( $text, array $expected ) {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $this->testEnvironment->withConfiguration(
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ $title->getNamespace() => true ],
+ 'smwgParserFeatures' => SMW_PARSER_STRICT | SMW_PARSER_INL_ERROR
+ ]
+ );
+
+ $parserData = new ParserData( $title, $parserOutput );
+
+ $inTextAnnotationParser = ApplicationFactory::getInstance()->newInTextAnnotationParser( $parserData );
+ $inTextAnnotationParser->parse( $text );
+
+ $this->assertEquals(
+ $expected['magicWords'],
+ $this->getMagicwords( $parserOutput )
+ );
+ }
+
+ /**
+ * @dataProvider textDataProvider
+ */
+ // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.CodeAnalysis.UnusedFunctionParameter
+ public function testGetMagicWords( $text, array $expected ) { // @codingStandardsIgnoreEnd
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $this->testEnvironment->withConfiguration( [
+ 'smwgShowFactboxEdit' => SMW_FACTBOX_HIDDEN,
+ 'smwgShowFactbox' => SMW_FACTBOX_HIDDEN
+ ]
+ );
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->any() )
+ ->method( 'getExtensionData' )
+ ->will( $this->returnValue( $expected['magicWords'] ) );
+
+ // MW 1.19, 1.20
+ $parserOutput->mSMWMagicWords = $expected['magicWords'];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Factbox(
+ $store,
+ new ParserData( $title, $parserOutput ),
+ $messageBuilder
+ );
+
+ if ( isset( $expected['preview'] ) && $expected['preview'] ) {
+ $instance->setPreviewFlag( true );
+ }
+
+ $reflector = new ReflectionClass( '\SMW\Factbox\Factbox' );
+
+ $magic = $reflector->getMethod( 'getMagicWords' );
+ $magic->setAccessible( true );
+
+ $result = $magic->invoke( $instance );
+
+ $this->assertInternalType( 'integer', $result );
+ $this->assertEquals( $expected['constants'], $result );
+ }
+
+ /**
+ * @return array
+ */
+ public function textDataProvider() {
+
+ $provider = [];
+
+ // #0 __NOFACTBOX__, this test should not generate a factbox output
+ $provider[] = [
+ 'Lorem ipsum dolor sit amet consectetuer auctor at quis' .
+ ' [[Foo::dictumst cursus]]. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' __NOFACTBOX__ ',
+ [
+ 'magicWords' => [ 'SMW_NOFACTBOX' ],
+ 'constants' => SMW_FACTBOX_HIDDEN,
+ 'textOutput' => ''
+ ]
+ ];
+
+ // #1 __SHOWFACTBOX__, this test should generate a factbox output
+ $provider[] = [
+ 'Lorem ipsum dolor sit amet consectetuer auctor at quis' .
+ ' [[Foo::dictumst cursus]]. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' __SHOWFACTBOX__',
+ [
+ 'magicWords' => [ 'SMW_SHOWFACTBOX' ],
+ 'constants' => SMW_FACTBOX_NONEMPTY,
+ 'textOutput' => 'smwfactboxhead' // lazy check because we use assertContains
+ ]
+ ];
+
+ // #2 empty
+ $provider[] = [
+ 'Lorem ipsum dolor sit amet consectetuer auctor at quis' .
+ ' [[Foo::dictumst cursus]]. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut',
+ [
+ 'magicWords' => null,
+ 'constants' => SMW_FACTBOX_HIDDEN,
+ 'textOutput' => ''
+ ]
+ ];
+
+ // #3 empty + preview option
+ $provider[] = [
+ 'Lorem ipsum dolor sit amet consectetuer auctor at quis' .
+ ' [[Foo::dictumst cursus]]. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut',
+ [
+ 'magicWords' => null,
+ 'preview' => true,
+ 'constants' => SMW_FACTBOX_HIDDEN,
+ 'textOutput' => ''
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ protected function getMagicwords( $parserOutput ) {
+
+ if ( method_exists( $parserOutput, 'getExtensionData' ) ) {
+ return $parserOutput->getExtensionData( 'smwmagicwords' );
+ }
+
+ return $parserOutput->mSMWMagicWords;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxTest.php
new file mode 100644
index 00000000..faabe166
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Factbox/FactboxTest.php
@@ -0,0 +1,559 @@
+<?php
+
+namespace SMW\Tests\Factbox;
+
+use ParserOutput;
+use ReflectionClass;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Factbox\Factbox;
+use SMW\ParserData;
+use SMW\SemanticData;
+use SMW\TableFormatter;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\Factbox\Factbox
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class FactboxTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->stringValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+
+ $this->testEnvironment->addConfiguration( 'smwgShowFactbox', SMW_FACTBOX_NONEMPTY );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ Factbox::class,
+ new Factbox( $store, $parserData )
+ );
+ }
+
+ public function testGetContent() {
+
+ $text = __METHOD__;
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ // Build Factbox stub object to encapsulate the method
+ // without the need for other dependencies to occur
+ $instance = $this->getMockBuilder( '\SMW\Factbox\Factbox' )
+ ->setConstructorArgs( [
+ $store,
+ $parserData
+ ] )
+ ->setMethods( [ 'fetchContent', 'getMagicWords' ] )
+ ->getMock();
+
+ $instance->expects( $this->any() )
+ ->method( 'getMagicWords' )
+ ->will( $this->returnValue( 'Lula' ) );
+
+ $instance->expects( $this->any() )
+ ->method( 'fetchContent' )
+ ->will( $this->returnValue( $text ) );
+
+ $this->assertFalse( $instance->isVisible() );
+
+ $instance->doBuild();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getContent()
+ );
+
+ $this->assertEquals(
+ $text,
+ $instance->getContent()
+ );
+
+ $this->assertTrue( $instance->isVisible() );
+ }
+
+ public function testGetContentRoundTripForNonEmptyContent() {
+
+ $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+
+ $this->testEnvironment->addConfiguration( 'smwgShowFactbox', SMW_FACTBOX_NONEMPTY );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'hasVisibleProperties' )
+ ->will( $this->returnValue( true ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $subject ] ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [ DIProperty::newFromUserLabel( 'SomeFancyProperty' ) ] ) );
+
+ $parserOutput = $this->setupParserOutput( $semanticData );
+
+ $instance = new Factbox(
+ $store,
+ new ParserData( $subject->getTitle(), $parserOutput )
+ );
+
+ $result = $instance->doBuild()->getContent();
+
+ $this->assertInternalType(
+ 'string',
+ $result
+ );
+
+ $this->assertContains(
+ $subject->getDBkey(),
+ $result
+ );
+
+ $this->assertEquals(
+ $subject->getTitle(),
+ $instance->getTitle()
+ );
+ }
+
+ public function testCreateTable() {
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new Factbox( $store, $parserData );
+
+ $reflector = new ReflectionClass( '\SMW\Factbox\Factbox' );
+ $createTable = $reflector->getMethod( 'createTable' );
+ $createTable->setAccessible( true );
+
+ $this->assertInternalType(
+ 'string',
+ $createTable->invoke( $instance, $parserData->getSemanticData() )
+ );
+ }
+
+ public function testTabs() {
+
+ $this->assertContains(
+ 'tab-facts-rendered',
+ Factbox::tabs( 'Foo' )
+ );
+
+ $this->assertContains(
+ 'tab-facts-derived',
+ Factbox::tabs( 'Foo', 'Bar' )
+ );
+ }
+
+ /**
+ * @dataProvider fetchContentDataProvider
+ */
+ public function testFetchContent( $parserData ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new Factbox(
+ $store,
+ $parserData
+ );
+
+ $reflector = new ReflectionClass( '\SMW\Factbox\Factbox' );
+
+ $fetchContent = $reflector->getMethod( 'fetchContent' );
+ $fetchContent->setAccessible( true );
+
+ $this->assertInternalType(
+ 'string',
+ $fetchContent->invoke( $instance, SMW_FACTBOX_NONEMPTY )
+ );
+
+ $this->assertEmpty(
+ $fetchContent->invoke( $instance, SMW_FACTBOX_HIDDEN )
+ );
+ }
+
+ /**
+ * @dataProvider contentDataProvider
+ */
+ public function testGetContentDataSimulation( $setup, $expected ) {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'hasVisibleSpecialProperties' )
+ ->will( $this->returnValue( $setup['hasVisibleSpecialProperties'] ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'hasVisibleProperties' )
+ ->will( $this->returnValue( $setup['hasVisibleProperties'] ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'isEmpty' )
+ ->will( $this->returnValue( $setup['isEmpty'] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $parserData->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( null ) );
+
+ // Build Factbox stub object to encapsulate the method
+ // without the need for other dependencies to occur
+ $factbox = $this->getMockBuilder( '\SMW\Factbox\Factbox' )
+ ->setConstructorArgs( [
+ $store,
+ $parserData
+ ] )
+ ->setMethods( [ 'createTable' ] )
+ ->getMock();
+
+ $factbox->expects( $this->any() )
+ ->method( 'createTable' )
+ ->will( $this->returnValue( $setup['invokedContent'] ) );
+
+ $reflector = new ReflectionClass( '\SMW\Factbox\Factbox' );
+ $fetchContent = $reflector->getMethod( 'fetchContent' );
+ $fetchContent->setAccessible( true );
+
+ $this->assertInternalType(
+ 'string',
+ $fetchContent->invoke( $factbox )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $fetchContent->invoke( $factbox, $setup['showFactbox'] )
+ );
+ }
+
+ /**
+ * Conditional content switcher to test combinations of
+ * SMW_FACTBOX_NONEMPTY and SMWSemanticData etc.
+ *
+ * @return array
+ */
+ public function contentDataProvider() {
+
+ $text = __METHOD__;
+ $provider = [];
+
+ $provider[] = [
+ [
+ 'hasVisibleSpecialProperties' => true,
+ 'hasVisibleProperties' => true,
+ 'isEmpty' => false,
+ 'showFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'invokedContent' => $text,
+ ],
+ $text // expected return
+ ];
+
+ $provider[] = [
+ [
+ 'hasVisibleSpecialProperties' => true,
+ 'hasVisibleProperties' => true,
+ 'isEmpty' => true,
+ 'showFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'invokedContent' => $text,
+ ],
+ $text // expected return
+ ];
+
+ $provider[] = [
+ [
+ 'hasVisibleSpecialProperties' => false,
+ 'hasVisibleProperties' => true,
+ 'isEmpty' => false,
+ 'showFactbox' => SMW_FACTBOX_SPECIAL,
+ 'invokedContent' => $text,
+ ],
+ '' // expected return
+ ];
+
+ $provider[] = [
+ [
+ 'hasVisibleSpecialProperties' => false,
+ 'hasVisibleProperties' => false,
+ 'isEmpty' => false,
+ 'showFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'invokedContent' => $text,
+ ],
+ '' // expected return
+ ];
+
+ $provider[] = [
+ [
+ 'hasVisibleSpecialProperties' => true,
+ 'hasVisibleProperties' => false,
+ 'isEmpty' => false,
+ 'showFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'invokedContent' => $text,
+ ],
+ '' // expected return
+ ];
+
+ return $provider;
+ }
+
+ public function testGetTableHeader() {
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $parserData = new ParserData(
+ $title,
+ new ParserOutput()
+ );
+
+ $parserData->setSemanticData( new SemanticData( DIWikiPage::newFromTitle( $title ) ) );
+ $parserData->getSemanticData()->addPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ DIWikiPage::newFromTitle( $title )
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new Factbox( $store, $parserData );
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ 'div class="smwrdflink"'
+ ],
+ $instance->doBuild()->getContent()
+ );
+ }
+
+ /**
+ * @dataProvider tableContentDataProvider
+ */
+ public function testGetTableContent( $test, $expected ) {
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $parserData = new ParserData(
+ $title,
+ new ParserOutput()
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property->expects( $this->any() )
+ ->method( 'isUserDefined' )
+ ->will( $this->returnValue( $test['isUserDefined'] ) );
+
+ $property->expects( $this->any() )
+ ->method( 'findPropertyTypeID' )
+ ->will( $this->returnValue( '_wpg' ) );
+
+ $property->expects( $this->any() )
+ ->method( 'isShown' )
+ ->will( $this->returnValue( $test['isShown'] ) );
+
+ $property->expects( $this->any() )
+ ->method( 'getLabel' )
+ ->will( $this->returnValue( 'Quuey' ) );
+
+ $property->expects( $this->any() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( \SMWDataItem::TYPE_PROPERTY ) );
+
+ $parserData->setSemanticData(
+ new SemanticData( DIWikiPage::newFromTitle( $title ) )
+ );
+
+ $parserData->getSemanticData()->addPropertyObjectValue(
+ $property,
+ DIWikiPage::newFromTitle( $title )
+ );
+
+ $instance = new Factbox( $store, $parserData );
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->doBuild()->getContent()
+ );
+ }
+
+ public function tableContentDataProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ [
+ 'isShown' => true,
+ 'isUserDefined' => true,
+ ],
+ [ 'class="smw-table-cell smwprops"' ]
+ ];
+
+ $provider[] = [
+ [
+ 'isShown' => false,
+ 'isUserDefined' => true,
+ ],
+ ''
+ ];
+
+ $provider[] = [
+ [
+ 'isShown' => true,
+ 'isUserDefined' => false,
+ ],
+ [ 'class="smw-table-cell smwspecs"' ]
+ ];
+
+ $provider[] = [
+ [
+ 'isShown' => false,
+ 'isUserDefined' => false,
+ ],
+ ''
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function fetchContentDataProvider() {
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $provider = [];
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'isEmpty' )
+ ->will( $this->returnValue( false ) );
+
+ $parserData = new ParserData(
+ $title,
+ new ParserOutput()
+ );
+
+ $parserData->setSemanticData( $semanticData );
+
+ $provider[] = [ $parserData ];
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ new DIProperty( '_SKEY') ] ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'isEmpty' )
+ ->will( $this->returnValue( false ) );
+
+ $parserData = new ParserData(
+ $title,
+ new ParserOutput()
+ );
+
+ $parserData->setSemanticData( $semanticData );
+
+ $provider[] = [ $parserData ];
+
+ return $provider;
+ }
+
+ protected function setupParserOutput( $semanticData ) {
+
+ $parserOutput = new ParserOutput();
+
+ if ( method_exists( $parserOutput, 'setExtensionData' ) ) {
+ $parserOutput->setExtensionData( 'smwdata', $semanticData );
+ } else {
+ $parserOutput->mSMWData = $semanticData;
+ }
+
+ return $parserOutput;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/GlobalFunctionsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/GlobalFunctionsTest.php
new file mode 100644
index 00000000..165c3dfb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/GlobalFunctionsTest.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class GlobalFunctionsTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @covers ::smwfGetLinker
+ * @test smwfGetLinker
+ *
+ * @since 1.9
+ */
+ public function testSmwfGetLinker() {
+ $instance = smwfGetLinker();
+
+ $this->assertInstanceOf( 'Linker', $instance );
+ }
+
+ /**
+ * @covers ::smwfNormalTitleDBKey
+ * @test smwfNormalTitleDBKey
+ *
+ * @since 1.9
+ */
+ public function testSmwfNormalTitleDBKey() {
+ $result = smwfNormalTitleDBKey( ' foo bar ' );
+
+ // Globals are ... but it can't be invoke ... well make my day
+ $expected = $GLOBALS['wgCapitalLinks'] ? 'Foo_bar' : 'foo_bar';
+ $this->assertEquals( $expected, $result );
+ }
+
+ /**
+ * @covers ::smwfHTMLtoUTF8
+ * @test smwfHTMLtoUTF8
+ *
+ * @since 1.9
+ */
+ public function testSmwfHTMLtoUTF8() {
+ $result = smwfHTMLtoUTF8( "\xc4\x88io bonas dans l'\xc3\xa9cole, &#x108;io bonas dans l'&eacute;cole!" );
+
+ $expected = "Ĉio bonas dans l'école, Ĉio bonas dans l'école!";
+ $this->assertEquals( $expected, $result );
+ }
+
+ /**
+ * @test Test if global functions are accessible
+ * @dataProvider getGlobalFunctions
+ *
+ * @param $function
+ */
+ public function testGlobalFunctionsAccessibility( $function ) {
+ $this->assertTrue( function_exists( $function ) );
+ }
+
+ /**
+ * @covers ::smwfEncodeMessages
+ * @test smwfEncodeMessages
+ * @dataProvider getEncodeMessagesDataProvider
+ *
+ * @param $message
+ * @param $type
+ * @param $separator
+ * @param $escape
+ */
+ public function testSmwfEncodeMessages( $message, $type, $separator, $escape ) {
+ $results = smwfEncodeMessages( $message );
+ $this->assertFalse( is_null( $results ) );
+ $this->assertTrue( is_string( $results ) );
+
+ $results = smwfEncodeMessages( $message, $type );
+ $this->assertFalse( is_null( $results ) );
+ $this->assertTrue( is_string( $results ) );
+
+ $results = smwfEncodeMessages( $message, $type, $separator );
+ $this->assertFalse( is_null( $results ) );
+ $this->assertTrue( is_string( $results ) );
+
+ $results = smwfEncodeMessages( $message, $type, $separator, $escape );
+ $this->assertFalse( is_null( $results ) );
+ $this->assertTrue( is_string( $results ) );
+ }
+
+ public function testSwfCountDown() {
+ $this->assertTrue( function_exists( 'swfCountDown' ) );
+ }
+
+ public function testSmwfCacheKeyOnPrefixedNamespace() {
+
+ $this->assertEquals(
+ smwfCacheKey( 'foo', 'bar' ),
+ smwfCacheKey( ':foo', 'bar' )
+ );
+ }
+
+ /**
+ * Provides available global functions
+ *
+ * @return array
+ */
+ public function getGlobalFunctions() {
+ return [
+ [ 'smwfNormalTitleDBKey' ],
+ [ 'smwfNormalTitleText' ],
+ [ 'smwfXMLContentEncode' ],
+ [ 'smwfHTMLtoUTF8' ],
+ [ 'smwfNumberFormat' ],
+ [ 'smwfEncodeMessages' ],
+ [ 'smwfGetStore' ],
+ [ 'smwfGetLinker' ],
+ ];
+ }
+
+ /**
+ * Provides messages
+ *
+ * @return array
+ */
+ public function getEncodeMessagesDataProvider() {
+ return [
+ [ [ '', '', '' ] , '', '', true ],
+ [ [ 'abc', 'ABC', '<span>Test</span>' ] , '', '', true ],
+ [ [ 'abc', 'ABC', '<span>Test</span>' ] , 'warning', '', true ],
+ [ [ 'abc', 'ABC', '<span>Test</span>' ] , 'info', ',', false ],
+ [ [ 'abc', 'ABC', '<span>Test</span>' ] , null, ',', false ],
+ [ [ 'abc', 'ABC', '<span>Test</span>' ] , '<span>Test</span>', ',', true ],
+ ];
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HashBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HashBuilderTest.php
new file mode 100644
index 00000000..85558d93
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HashBuilderTest.php
@@ -0,0 +1,146 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataModel\ContainerSemanticData;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\HashBuilder;
+use SMW\SemanticData;
+use Title;
+
+/**
+ * @covers \SMW\HashBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class HashBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider segmentProvider
+ */
+ public function testTitleRoundTrip( $namespace, $title, $interwiki , $fragment ) {
+
+ $title = Title::makeTitle( $namespace, $title, $fragment, $interwiki );
+
+ $this->assertEquals(
+ $title,
+ HashBuilder::newTitleFromHash(
+ HashBuilder::getHashIdForTitle( $title )
+ )
+ );
+ }
+
+ /**
+ * @dataProvider segmentProvider
+ */
+ public function testDiWikiPageRoundTrip( $namespace, $title, $interwiki, $subobjectName ) {
+
+ $dataItem = new DIWikiPage( $title, $namespace, $interwiki, $subobjectName );
+
+ $this->assertEquals(
+ $dataItem,
+ HashBuilder::newDiWikiPageFromHash(
+ HashBuilder::getHashIdForDiWikiPage( $dataItem )
+ )
+ );
+ }
+
+ public function testPredefinedProperty() {
+
+ $instance = new HashBuilder();
+
+ $property = new DIProperty( '_MDAT' );
+ $dataItem = $property->getDiWikiPage();
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->newDiWikiPageFromHash(
+ $instance->getHashIdForDiWikiPage( $dataItem )
+ )
+ );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->newDiWikiPageFromHash(
+ $instance->createHashIdFromSegments( $property->getKey(), SMW_NS_PROPERTY )
+ )
+ );
+ }
+
+ public function testContentHashId() {
+
+ $hash = HashBuilder::createFromContent( 'Foo' );
+
+ $this->assertInternalType(
+ 'string',
+ $hash
+ );
+
+ $this->assertSame(
+ $hash,
+ HashBuilder::createFromContent( [ 'Foo' ] )
+ );
+
+ $this->assertContains(
+ 'Bar',
+ HashBuilder::createFromContent( [ 'Foo' ], 'Bar' )
+ );
+ }
+
+ public function testCreateFromSemanticData() {
+
+ $semanticData = new SemanticData(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $this->assertInternalType(
+ 'string',
+ HashBuilder::createFromSemanticData( $semanticData )
+ );
+ }
+
+ public function testCreateFromSemanticDataWithSubSemanticDataAndPHPSerialization() {
+
+ $semanticData = new SemanticData(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $containerSemanticData = new ContainerSemanticData(
+ new DIWikiPage( __METHOD__, NS_MAIN, '', 'Foo' )
+ );
+
+ $containerSemanticData->addSubSemanticData(
+ new ContainerSemanticData( new DIWikiPage( __METHOD__, NS_MAIN, '', 'Foo2' ) )
+ );
+
+ $semanticData->addSubSemanticData(
+ $containerSemanticData
+ );
+
+ $semanticData->addSubSemanticData(
+ new ContainerSemanticData( new DIWikiPage( __METHOD__, NS_MAIN, '', 'Bar' ) )
+ );
+
+ $sem = serialize( $semanticData );
+
+ $this->assertInternalType(
+ 'string',
+ HashBuilder::createFromSemanticData( unserialize( $sem ) )
+ );
+ }
+
+ public function segmentProvider() {
+
+ $provider[] = [ NS_FILE, 'ichi', '', '' ];
+ $provider[] = [ NS_HELP, 'ichi', 'ni', '' ];
+ $provider[] = [ NS_MAIN, 'ichi maru', 'ni', 'san' ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HierarchyLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HierarchyLookupTest.php
new file mode 100644
index 00000000..b335a19d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/HierarchyLookupTest.php
@@ -0,0 +1,421 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\HierarchyLookup;
+
+/**
+ * @covers \SMW\HierarchyLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class HierarchyLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $cache;
+ private $spyLogger;
+
+ protected function setUp() {
+
+ $this->spyLogger = TestEnvironment::newSpyLogger();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ HierarchyLookup::class,
+ new HierarchyLookup( $this->store, $this->cache )
+ );
+ }
+
+ public function testAddChangePropListener() {
+
+ $changePropListener = $this->getMockBuilder( '\SMW\ChangePropListener' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changePropListener->expects( $this->at( 0 ) )
+ ->method( 'addListenerCallback' )
+ ->with(
+ $this->equalTo( '_SUBP' ),
+ $this->anything() );
+
+ $changePropListener->expects( $this->at( 1 ) )
+ ->method( 'addListenerCallback' )
+ ->with(
+ $this->equalTo( '_SUBC' ),
+ $this->anything() );
+
+ $instance = new HierarchyLookup(
+ $this->store,
+ $this->cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->addListenersTo( $changePropListener );
+ }
+
+ public function testVerifySubpropertyForOnNonCachedLookup() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new HierarchyLookup(
+ $store,
+ $cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $property = new DIProperty( 'Foo' );
+ $instance->hasSubproperty( $property );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->hasSubproperty( $property )
+ );
+ }
+
+ public function testFindSubpropertyList() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $expected = [
+ DIWikiPage::newFromText( 'Bar', SMW_NS_PROPERTY )
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( new DIProperty( '_SUBP' ) ),
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->anything() )
+ ->will( $this->returnValue( $expected ) );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new HierarchyLookup(
+ $store,
+ $cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->findSubpropertyList( $property )
+ );
+ }
+
+ public function testGetConsecutiveSubpropertyList() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $expected = [
+ new DIProperty( 'Bar' ),
+ new DIProperty( 'Foobar' )
+ ];
+
+ $a = DIWikiPage::newFromText( 'Bar', SMW_NS_PROPERTY );
+
+ $this->store->expects( $this->at( 0 ) )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( new DIProperty( '_SUBP' ) ),
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $a ] ) );
+
+ $b = DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY );
+
+ $this->store->expects( $this->at( 1 ) )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( new DIProperty( '_SUBP' ) ),
+ $this->equalTo( $a ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $b ] ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'save' )
+ ->with(
+ $this->stringContains( ':smw:hierarchy:25840d7839e2fe0369c3fe16014d21d1' ),
+ $this->anything() );
+
+ $instance = new HierarchyLookup(
+ $this->store,
+ $this->cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setSubpropertyDepth( 2 );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getConsecutiveHierarchyList( $property )
+ );
+ }
+
+ public function testGetConsecutiveCachedSubpropertyList() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $expected = [
+ new DIProperty( 'Bar' ),
+ new DIProperty( 'Foobar' )
+ ];
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( [ 'Foo' => [ 'Bar', 'Foobar' ] ] ) );
+
+ $this->cache->expects( $this->never() )
+ ->method( 'save' );
+
+ $instance = new HierarchyLookup(
+ $this->store,
+ $this->cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setSubpropertyDepth( 2 );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getConsecutiveHierarchyList( $property )
+ );
+ }
+
+ public function testGetConsecutiveSubcategoryList() {
+
+ $category = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $expected = [
+ new DIWikiPage( 'Bar', NS_CATEGORY ),
+ new DIWikiPage( 'Foobar', NS_CATEGORY )
+ ];
+
+ $a = DIWikiPage::newFromText( 'Bar', NS_CATEGORY );
+
+ $this->store->expects( $this->at( 0 ) )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( new DIProperty( '_SUBC' ) ),
+ $this->equalTo( $category ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $a ] ) );
+
+ $b = DIWikiPage::newFromText( 'Foobar', NS_CATEGORY );
+
+ $this->store->expects( $this->at( 1 ) )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( new DIProperty( '_SUBC' ) ),
+ $this->equalTo( $a ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $b ] ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'save' )
+ ->with(
+ $this->stringContains( ':smw:hierarchy:d27ae8a4539ee4c7ab76aedcbf1c08c0' ),
+ $this->anything() );
+
+ $instance = new HierarchyLookup(
+ $this->store,
+ $this->cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setSubcategoryDepth( 2 );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getConsecutiveHierarchyList( $category )
+ );
+ }
+
+ public function testGetConsecutiveCachedSubcategoryList() {
+
+ $category = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $expected = [
+ new DIWikiPage( 'Bar', NS_CATEGORY ),
+ new DIWikiPage( 'Foobar', NS_CATEGORY )
+ ];
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( [ 'Foo' => [ 'Bar', 'Foobar' ] ] ) );
+
+ $this->cache->expects( $this->never() )
+ ->method( 'save' );
+
+ $instance = new HierarchyLookup(
+ $this->store,
+ $this->cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setSubcategoryDepth( 2 );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getConsecutiveHierarchyList( $category )
+ );
+ }
+
+ public function testGetConsecutiveHierarchyListWithInvaidTypeThrowsException() {
+
+ $instance = new HierarchyLookup(
+ $this->store,
+ $this->cache
+ );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+
+ $instance->getConsecutiveHierarchyList( new DIWikiPage( __METHOD__, NS_MAIN ) );
+ }
+
+ public function testFindSubcategoryList() {
+
+ $category = DIWikiPage::newFromText( 'Foo', NS_CATEGORY );
+
+ $expected = [
+ DIWikiPage::newFromText( 'Bar', NS_CATEGORY )
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( new DIProperty( '_SUBC' ) ),
+ $this->equalTo( $category ),
+ $this->anything() )
+ ->will( $this->returnValue( $expected ) );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new HierarchyLookup(
+ $store,
+ $cache
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->findSubcategoryList( $category )
+ );
+ }
+
+ public function testDisabledSubpropertyLookup() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->never() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new HierarchyLookup( $store, $cache );
+ $instance->setSubpropertyDepth( 0 );
+
+ $this->assertFalse(
+ $instance->hasSubproperty( new DIProperty( 'Foo' ) )
+ );
+ }
+
+ public function testDisabledSubcategoryLookup() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->never() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new HierarchyLookup( $store, $cache );
+ $instance->setSubcategoryDepth( 0 );
+
+ $this->assertFalse(
+ $instance->hasSubcategory( DIWikiPage::newFromText( 'Foo', NS_CATEGORY ) )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/DispatchingContentCreatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/DispatchingContentCreatorTest.php
new file mode 100644
index 00000000..7dfe78a7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/DispatchingContentCreatorTest.php
@@ -0,0 +1,133 @@
+<?php
+
+namespace SMW\Tests\Importer\ContentCreators;
+
+use SMW\Importer\ContentCreators\DispatchingContentCreator;
+use SMW\Importer\ImportContents;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Importer\ContentCreators\DispatchingContentCreator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DispatchingContentCreatorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $wikiImporter;
+ private $messageReporter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $importStreamSource = $this->getMockBuilder( '\ImportStreamSource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->wikiImporter = $this->getMockBuilder( '\WikiImporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->messageReporter = $this->getMockBuilder( '\Onoi\MessageReporter\MessageReporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\ContentCreators\DispatchingContentCreator',
+ new DispatchingContentCreator( [] )
+ );
+ }
+
+ public function testCanCreateContentsFor() {
+
+ $importContents = new ImportContents();
+ $importContents->setContentType( 'Foo' );
+
+ $contentCreator = $this->getMockBuilder( '\SMW\Importer\ContentCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentCreator->expects( $this->any() )
+ ->method( 'canCreateContentsFor' )
+ ->with( $this->equalTo( $importContents ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new DispatchingContentCreator(
+ [
+ $contentCreator
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->canCreateContentsFor( $importContents )
+ );
+ }
+
+ public function testDoCreateFrom() {
+
+ $importContents = new ImportContents();
+ $importContents->setContentType( 'Foo' );
+
+ $contentCreator = $this->getMockBuilder( '\SMW\Importer\ContentCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentCreator->expects( $this->any() )
+ ->method( 'canCreateContentsFor' )
+ ->will( $this->returnValue( true ) );
+
+ $contentCreator->expects( $this->any() )
+ ->method( 'create' )
+ ->with( $this->equalTo( $importContents ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new DispatchingContentCreator(
+ [
+ $contentCreator
+ ]
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $this->assertTrue(
+ $instance->create( $importContents )
+ );
+ }
+
+ public function testDoCreateFromOnNonMatchableCreatorThrowsException() {
+
+ $importContents = new ImportContents();
+ $importContents->setContentType( 'Foo' );
+
+ $contentCreator = $this->getMockBuilder( '\SMW\Importer\ContentCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentCreator->expects( $this->any() )
+ ->method( 'canCreateContentsFor' )
+ ->will( $this->returnValue( false ) );
+
+ $contentCreator->expects( $this->never() )
+ ->method( 'create' );
+
+ $instance = new DispatchingContentCreator(
+ [
+ $contentCreator
+ ]
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->create( $importContents );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/TextContentCreatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/TextContentCreatorTest.php
new file mode 100644
index 00000000..860b453c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/TextContentCreatorTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\Importer\ContentCreators;
+
+use SMW\Importer\ContentCreators\TextContentCreator;
+use SMW\Importer\ImportContents;
+
+/**
+ * @covers \SMW\Importer\ContentCreators\TextContentCreator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TextContentCreatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $pageCreator;
+ private $connection;
+ private $messageReporter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->messageReporter = $this->getMockBuilder( '\Onoi\MessageReporter\MessageReporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\ContentCreators\TextContentCreator',
+ new TextContentCreator( $this->pageCreator, $this->connection )
+ );
+ }
+
+ public function testCanCreateContentsFor() {
+
+ $instance = new TextContentCreator(
+ $this->pageCreator,
+ $this->connection
+ );
+
+ $importContents = new ImportContents();
+ $importContents->setContentType( ImportContents::CONTENT_TEXT );
+
+ $this->assertTrue(
+ $instance->canCreateContentsFor( $importContents )
+ );
+ }
+
+ public function testDoCreateFrom() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) {
+ return call_user_func( $callback ); }
+ ) );
+
+ $page = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page->expects( $this->once() )
+ ->method( 'doEditContent' );
+
+ $this->pageCreator->expects( $this->atLeastOnce() )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $page ) );
+
+ $instance = new TextContentCreator(
+ $this->pageCreator,
+ $this->connection
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $importContents = new ImportContents();
+ $importContents->setContentType( ImportContents::CONTENT_TEXT );
+ $importContents->setName( 'Foo' );
+
+ $instance->create( $importContents );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/XmlContentCreatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/XmlContentCreatorTest.php
new file mode 100644
index 00000000..f9478705
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentCreators/XmlContentCreatorTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\Importer\ContentCreators;
+
+use SMW\Importer\ContentCreators\XmlContentCreator;
+use SMW\Importer\ImportContents;
+
+/**
+ * @covers \SMW\Importer\ContentCreators\XmlContentCreator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class XmlContentCreatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $importerServiceFactory;
+ private $wikiImporter;
+ private $messageReporter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ if ( !interface_exists( '\ImportSource' ) ) {
+ $this->markTestSkipped( "ImportSource interface is unknown (MW 1.25-)" );
+ }
+
+ $importStreamSource = $this->getMockBuilder( '\ImportStreamSource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->wikiImporter = $this->getMockBuilder( '\WikiImporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->importerServiceFactory = $this->getMockBuilder( '\SMW\Services\ImporterServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->importerServiceFactory->expects( $this->any() )
+ ->method( 'newImportStreamSource' )
+ ->will( $this->returnValue( $importStreamSource ) );
+
+ $this->importerServiceFactory->expects( $this->any() )
+ ->method( 'newWikiImporter' )
+ ->will( $this->returnValue( $this->wikiImporter ) );
+
+ $this->messageReporter = $this->getMockBuilder( '\Onoi\MessageReporter\MessageReporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\ContentCreators\XmlContentCreator',
+ new XmlContentCreator( $this->importerServiceFactory )
+ );
+ }
+
+ public function testCanCreateContentsFor() {
+
+ $instance = new XmlContentCreator(
+ $this->importerServiceFactory
+ );
+
+ $importContents = new ImportContents();
+ $importContents->setContentType( ImportContents::CONTENT_XML );
+
+ $this->assertTrue(
+ $instance->canCreateContentsFor( $importContents )
+ );
+ }
+
+ public function testDoCreateFrom() {
+
+ $this->wikiImporter->expects( $this->atLeastOnce() )
+ ->method( 'doImport' );
+
+ $instance = new XmlContentCreator(
+ $this->importerServiceFactory
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $importContents = new ImportContents();
+ $importContents->setContentType( ImportContents::CONTENT_XML );
+ $importContents->setContentsFile( 'Foo' );
+
+ $instance->create( $importContents );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentModellerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentModellerTest.php
new file mode 100644
index 00000000..968b0d61
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ContentModellerTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace SMW\Tests\Importer;
+
+use SMW\Importer\ContentModeller;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Importer\ContentModeller
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ContentModellerTest extends \PHPUnit_Framework_TestCase {
+
+ private $contentModeller;
+ private $testEnvironment;
+ private $fixtures;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->contentModeller = new ContentModeller();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->fixtures = __DIR__ . '/Fixtures';
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ContentModeller::class,
+ new ContentModeller()
+ );
+ }
+
+ public function testMakeContentList() {
+
+ $contents = [
+ 'description' => '...',
+ 'import' => [
+ 'page' => 'Foo',
+ 'version' => 1
+ ]
+ ];
+
+ $instance = new ContentModeller();
+
+ $contents = $instance->makeContentList( 'Foo', $contents );
+
+ foreach ( $contents as $content ) {
+ $this->assertInstanceOf(
+ '\SMW\Importer\ImportContents',
+ $content
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/InvalidJsonContent/invalid.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/InvalidJsonContent/invalid.json
new file mode 100644
index 00000000..dc3f51d0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/InvalidJsonContent/invalid.json
@@ -0,0 +1,26 @@
+{
+ "description": "Test import",
+ "import": [
+ {
+ "page": "Smw import foaf",
+ "namespace": "NS_MEDIAWIKI",
+ "contents": {
+ "importFrom": "foaf.txt"
+ },
+ "options": {
+ "canReplace": false
+ },
+ },
+ {
+ "page": "Foaf:knows",
+ "namespace": "SMW_NS_PROPERTY",
+ "contents": "* [[Imported from::foaf:knows]]",
+ "options": {
+ "canReplace": false
+ }
+ }
+ ],
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/MissingSections/error.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/MissingSections/error.json
new file mode 100644
index 00000000..5bfb659a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/MissingSections/error.json
@@ -0,0 +1,16 @@
+{
+ "description": "Test import",
+ "import": [
+ {
+ "contents": {
+ "importFrom": "foaf.txt"
+ },
+ "options": {
+ "canReplace": false
+ }
+ }
+ ],
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/NoImportFormat/error.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/NoImportFormat/error.json
new file mode 100644
index 00000000..732ddca2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/NoImportFormat/error.json
@@ -0,0 +1,6 @@
+{
+ "description": "Test import",
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/content.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/content.json
new file mode 100644
index 00000000..9dd4dc68
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/content.json
@@ -0,0 +1,26 @@
+{
+ "description": "Test import",
+ "import": [
+ {
+ "page": "Smw import foaf",
+ "namespace": "NS_MEDIAWIKI",
+ "contents": {
+ "importFrom": "foaf.txt"
+ },
+ "options": {
+ "canReplace": false
+ }
+ },
+ {
+ "page": "Foaf:knows",
+ "namespace": "SMW_NS_PROPERTY",
+ "contents": "* [[Imported from::foaf:knows]]",
+ "options": {
+ "canReplace": false
+ }
+ }
+ ],
+ "meta": {
+ "version": "1"
+ }
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/foaf.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/foaf.txt
new file mode 100644
index 00000000..15106fc0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/Fixtures/ValidTextContent/foaf.txt
@@ -0,0 +1,13 @@
+http://xmlns.com/foaf/0.1/|[http://www.foaf-project.org/ Friend Of A Friend]
+ name|Type:Text
+ homepage|Type:URL
+ mbox|Type:Email
+ mbox_sha1sum|Type:Text
+ depiction|Type:URL
+ phone|Type:Text
+ Person|Category
+ Organization|Category
+ knows|Type:Page
+ member|Type:Page
+
+[[Category:Imported vocabulary]] \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImportContentsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImportContentsTest.php
new file mode 100644
index 00000000..69099ee3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImportContentsTest.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace SMW\Tests\Importer;
+
+use SMW\Importer\ImportContents;
+
+/**
+ * @covers \SMW\Importer\ImportContents
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ImportContentsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\ImportContents',
+ new ImportContents()
+ );
+ }
+
+ public function testDescription() {
+
+ $instance = new ImportContents();
+
+ $instance->setDescription( 'Foo' );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->getDescription()
+ );
+ }
+
+ public function testVersion() {
+
+ $instance = new ImportContents();
+
+ $instance->setVersion( '1' );
+
+ $this->assertSame(
+ 1,
+ $instance->getVersion()
+ );
+ }
+
+ public function testName() {
+
+ $instance = new ImportContents();
+
+ $instance->setName( 'Foo' );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->getName()
+ );
+ }
+
+ public function testNamespace() {
+
+ $instance = new ImportContents();
+
+ $instance->setNamespace( 'Foo' );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->getNamespace()
+ );
+ }
+
+ public function testContents() {
+
+ $instance = new ImportContents();
+
+ $instance->setContents( 'Foo' );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->getContents()
+ );
+ }
+
+ public function testContentType() {
+
+ $instance = new ImportContents();
+
+ $instance->setContentType( 'Foo' );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->getContentType()
+ );
+ }
+
+ public function testError() {
+
+ $instance = new ImportContents();
+
+ $instance->addError( 'Foo' );
+
+ $this->assertSame(
+ [ 'Foo' ],
+ $instance->getErrors()
+ );
+ }
+
+ public function testOptions() {
+
+ $instance = new ImportContents();
+
+ $instance->setOptions( 'Foo' );
+
+ $this->assertSame(
+ [ 'Foo' ],
+ $instance->getOptions()
+ );
+
+ $this->assertFalse(
+ $instance->getOption( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImporterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImporterTest.php
new file mode 100644
index 00000000..0db5f2ff
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/ImporterTest.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace SMW\Tests\Importer;
+
+use SMW\Importer\ContentIterator;
+use SMW\Importer\ImportContents;
+use SMW\Importer\Importer;
+use SMW\Importer\JsoncontentIterator;
+use SMW\Importer\JsonImportContentsFileDirReader;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Importer\Importer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ImporterTest extends \PHPUnit_Framework_TestCase {
+
+ private $spyMessageReporter;
+ private $testEnvironment;
+ private $contentIterator;
+ private $jsonImportContentsFileDirReader;
+ private $contentCreator;
+ private $messageReporter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->jsonImportContentsFileDirReader = $this->getMockBuilder( JsonImportContentsFileDirReader::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->contentIterator = $this->getMockBuilder( ContentIterator::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->contentCreator = $this->getMockBuilder( '\SMW\Importer\ContentCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->messageReporter = $this->getMockBuilder( '\Onoi\MessageReporter\MessageReporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\Importer',
+ new Importer( $this->contentIterator, $this->contentCreator )
+ );
+ }
+
+ public function testDisabled() {
+
+ $spyMessageReporter = $this->testEnvironment->getUtilityFactory()->newSpyMessageReporter();
+
+ $instance = new Importer(
+ new JsoncontentIterator( $this->jsonImportContentsFileDirReader ),
+ $this->contentCreator
+ );
+
+ $instance->setMessageReporter( $spyMessageReporter );
+ $instance->isEnabled( false );
+
+ $instance->doImport();
+
+ $this->assertContains(
+ 'Skipping the import process',
+ $spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testDoImport() {
+
+ $importContents = new ImportContents();
+
+ $importContents->setName( 'Foo' );
+ $importContents->setVersion( 1 );
+
+ $page = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jsonImportContentsFileDirReader->expects( $this->atLeastOnce() )
+ ->method( 'getContentList' )
+ ->will( $this->returnValue( [ 'Foo' => [ $importContents ] ] ) );
+
+ $this->jsonImportContentsFileDirReader->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->contentCreator->expects( $this->atLeastOnce() )
+ ->method( 'create' );
+
+ $instance = new Importer(
+ new JsoncontentIterator( $this->jsonImportContentsFileDirReader ),
+ $this->contentCreator
+ );
+
+ $instance->setMessageReporter( $this->messageReporter );
+ $instance->setReqVersion( 1 );
+
+ $instance->doImport();
+ }
+
+ public function testDoImportWithError() {
+
+ $importContents = new ImportContents();
+
+ $importContents->addError( 'Bar' );
+ $importContents->setVersion( 1 );
+
+ $this->jsonImportContentsFileDirReader->expects( $this->atLeastOnce() )
+ ->method( 'getContentList' )
+ ->will( $this->returnValue( [ 'Foo' => [ $importContents ] ] ) );
+
+ $this->jsonImportContentsFileDirReader->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [ 'Error' ] ) );
+
+ $this->contentCreator->expects( $this->never() )
+ ->method( 'create' );
+
+ $instance = new Importer(
+ new JsoncontentIterator( $this->jsonImportContentsFileDirReader ),
+ $this->contentCreator
+ );
+
+ $instance->setMessageReporter( $this->messageReporter );
+ $instance->setReqVersion( 1 );
+
+ $instance->doImport();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonContentIteratorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonContentIteratorTest.php
new file mode 100644
index 00000000..a7bb118a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonContentIteratorTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\Importer;
+
+use SMW\Importer\JsonContentIterator;
+use SMW\Importer\JsonImportContentsFileDirReader;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Importer\JsonContentIterator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class JsonContentIteratorTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $jsonImportContentsFileDirReader;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->jsonImportContentsFileDirReader = $this->getMockBuilder( JsonImportContentsFileDirReader::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\JsonContentIterator',
+ new JsonContentIterator( $this->jsonImportContentsFileDirReader )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\ContentIterator',
+ new JsonContentIterator( $this->jsonImportContentsFileDirReader )
+ );
+ }
+
+ public function testGetIterator() {
+
+ $this->jsonImportContentsFileDirReader->expects( $this->atLeastOnce() )
+ ->method( 'getContentList' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new JsonContentIterator(
+ $this->jsonImportContentsFileDirReader
+ );
+
+ $this->assertInstanceOf(
+ '\Iterator',
+ $instance->getIterator()
+ );
+ }
+
+ public function testGetDescription() {
+
+ $instance = new JsonContentIterator(
+ $this->jsonImportContentsFileDirReader
+ );
+
+ $instance->setDescription( 'Foo' );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->getDescription()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonImportContentsFileDirReaderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonImportContentsFileDirReaderTest.php
new file mode 100644
index 00000000..c4965e52
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Importer/JsonImportContentsFileDirReaderTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace SMW\Tests\Importer;
+
+use SMW\Importer\ContentModeller;
+use SMW\Importer\JsonImportContentsFileDirReader;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Importer\JsonImportContentsFileDirReader
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class JsonImportContentsFileDirReaderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $contentModeller;
+ private $testEnvironment;
+ private $fixtures;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->contentModeller = new ContentModeller();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->fixtures = __DIR__ . '/Fixtures';
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ JsonImportContentsFileDirReader::class,
+ new JsonImportContentsFileDirReader( $this->contentModeller, $this->fixtures )
+ );
+ }
+
+ public function testGetContentList() {
+
+ $instance = new JsonImportContentsFileDirReader(
+ $this->contentModeller,
+ [ $this->fixtures . '/ValidTextContent' ]
+ );
+
+ $contents = $instance->getContentList();
+
+ $this->assertArrayHasKey(
+ 'content.json',
+ $contents
+ );
+
+ foreach ( $contents as $content ) {
+ foreach ( $content as $importContents ) {
+ $this->assertInstanceOf(
+ '\SMW\Importer\ImportContents',
+ $importContents
+ );
+ }
+ }
+ }
+
+ public function testGetContentListOnFalseImportFormat() {
+
+ $instance = new JsonImportContentsFileDirReader(
+ $this->contentModeller,
+ [ $this->fixtures . '/NoImportFormat' ]
+ );
+
+ $this->assertEmpty(
+ $instance->getContentList()
+ );
+ }
+
+ public function testGetContentListOnMissingSections() {
+
+ $instance = new JsonImportContentsFileDirReader(
+ $this->contentModeller,
+ [ $this->fixtures . '/MissingSections' ]
+ );
+
+ $contents = $instance->getContentList();
+
+ $this->assertArrayHasKey(
+ 'error.json',
+ $contents
+ );
+ }
+
+ public function testGetContentListWithInvalidPath() {
+
+ $instance = new JsonImportContentsFileDirReader(
+ $this->contentModeller,
+ [ __DIR__ . '/InvalidPath' ]
+ );
+
+ $this->assertEmpty(
+ $instance->getContentList()
+ );
+ }
+
+ public function testGetContentListOnInvalidJsonThrowsException() {
+
+ $instance = new JsonImportContentsFileDirReader(
+ $this->contentModeller,
+ [ $this->fixtures . '/InvalidJsonContent' ]
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getContentList();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/InMemoryPoolCacheTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/InMemoryPoolCacheTest.php
new file mode 100644
index 00000000..ea11cd54
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/InMemoryPoolCacheTest.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\InMemoryPoolCache;
+
+/**
+ * @covers \SMW\InMemoryPoolCache
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class InMemoryPoolCacheTest extends \PHPUnit_Framework_TestCase {
+
+ protected function tearDown() {
+ InMemoryPoolCache::getInstance()->clear();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $cacheFactory = $this->getMockBuilder( '\SMW\CacheFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\InMemoryPoolCache',
+ new InMemoryPoolCache( $cacheFactory )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\InMemoryPoolCache',
+ InMemoryPoolCache::getInstance()
+ );
+ }
+
+ public function testPoolCache() {
+
+ $instance = InMemoryPoolCache::getInstance();
+
+ $this->assertInstanceOf(
+ '\Onoi\Cache\Cache',
+ $instance->getPoolCacheById( 'Foo' )
+ );
+
+ $instance->getPoolCacheById( 'Foo' )->save( 'Bar', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->getPoolCacheById( 'Foo' )->fetch( 'Bar' )
+ );
+
+ $instance->resetPoolCacheById( 'Foo' );
+ }
+
+ public function testGetStats() {
+
+ $instance = InMemoryPoolCache::getInstance();
+
+ $instance->getPoolCacheById( 'Foo' )->save( 'Bar', 42 );
+
+ $this->assertNotEmpty(
+ $instance->getStats()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getStats( InMemoryPoolCache::FORMAT_PLAIN )
+ );
+
+ $this->assertContains(
+ 'ul',
+ $instance->getStats( InMemoryPoolCache::FORMAT_HTML )
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getStats( InMemoryPoolCache::FORMAT_JSON )
+ );
+
+ $instance->resetPoolCacheById( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/IteratorFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/IteratorFactoryTest.php
new file mode 100644
index 00000000..f3312ae7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/IteratorFactoryTest.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\IteratorFactory;
+
+/**
+ * @covers \SMW\IteratorFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class IteratorFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstructResultIterator() {
+
+ $instance = new IteratorFactory();
+
+ $result = $this->getMockBuilder( '\ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\ResultIterator',
+ $instance->newResultIterator( $result )
+ );
+ }
+
+ public function testCanConstructMappingIterator() {
+
+ $instance = new IteratorFactory();
+
+ $iterator = $this->getMockBuilder( '\ArrayIterator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\MappingIterator',
+ $instance->newMappingIterator( $iterator, function(){
+ } )
+ );
+ }
+
+ public function testCanConstructChunkedIterator() {
+
+ $instance = new IteratorFactory();
+
+ $iterator = $this->getMockBuilder( '\Iterator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\ChunkedIterator',
+ $instance->newChunkedIterator( $iterator )
+ );
+ }
+
+ public function testCanConstructAppendIterator() {
+
+ $instance = new IteratorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\AppendIterator',
+ $instance->newAppendIterator()
+ );
+ }
+
+ public function testCanConstructCsvFileIterator() {
+
+ $instance = new IteratorFactory();
+
+ $this->setExpectedException( 'SMW\Exception\FileNotFoundException' );
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\CsvFileIterator',
+ $instance->newCsvFileIterator( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/AppendIteratorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/AppendIteratorTest.php
new file mode 100644
index 00000000..617d244f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/AppendIteratorTest.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace SMW\Tests\Iterators;
+
+use SMW\Iterators\AppendIterator;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Iterators\AppendIterator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class AppendIteratorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ AppendIterator::class,
+ new AppendIterator()
+ );
+ }
+
+ /**
+ * @dataProvider iterableProvider
+ */
+ public function testCount( $iterable, $expected ) {
+
+ $instance = new AppendIterator();
+ $instance->add( $iterable );
+
+ $this->assertEquals(
+ $expected,
+ $instance->count()
+ );
+ }
+
+ public function testAddOnNonIterableThrowsException() {
+
+ $instance = new AppendIterator();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->add( 'Foo' );
+ }
+
+ public function iterableProvider() {
+
+ $provider[] = [
+ [
+ 1, 42, 1001, 9999
+ ],
+ 4
+ ];
+
+ $iterator = new AppendIterator();
+ $iterator->add( [ 0 , 1 ] );
+
+ $provider[] = [
+ $iterator,
+ 2
+ ];
+
+ $iterator = new AppendIterator();
+ $iterator->add( [ 0 , 1 ] );
+ $iterator->add( $iterator );
+
+ $provider[] = [
+ $iterator,
+ 4
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ChunkedIteratorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ChunkedIteratorTest.php
new file mode 100644
index 00000000..449adfdd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ChunkedIteratorTest.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace SMW\Tests\Iterators;
+
+use SMW\Iterators\ChunkedIterator;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Iterators\ChunkedIterator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChunkedIteratorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ChunkedIterator::class,
+ new ChunkedIterator( [] )
+ );
+ }
+
+ public function testChunkedOnArray() {
+
+ $result = [
+ 1, 42, 1001, 9999
+ ];
+
+ $instance = new ChunkedIterator( $result, 2 );
+
+ foreach ( $instance as $chunk ) {
+ $this->assertCount(
+ 2,
+ $chunk
+ );
+ }
+
+ $chunks = iterator_to_array( $instance, false );
+
+ $this->assertEquals(
+ [1, 42],
+ $chunks[0]
+ );
+
+ $this->assertEquals(
+ [1001, 9999],
+ $chunks[1]
+ );
+ }
+
+ public function testInvalidConstructorArgumentThrowsException() {
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance = new ChunkedIterator( 2 );
+ }
+
+ public function testInvalidChunkSizeArgumentThrowsException() {
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance = new ChunkedIterator( [], -1 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/CsvFileIteratorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/CsvFileIteratorTest.php
new file mode 100644
index 00000000..abe8299b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/CsvFileIteratorTest.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace SMW\Tests\Iterators;
+
+use SMW\Iterators\CsvFileIterator;
+use SMW\Utils\TempFile;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Iterators\CsvFileIterator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CsvFileIteratorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $file;
+ private $tempFile;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->tempFile = new TempFile();
+ $this->file = $this->tempFile->get( 'test.csv' );
+
+ $this->tempFile->write( $this->file, 'Foo' );
+ }
+
+ protected function tearDown() {
+ $this->tempFile->delete( $this->file );
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CsvFileIterator::class,
+ new CsvFileIterator( $this->file )
+ );
+ }
+
+ public function testInvalidFileThrowsException() {
+
+ $this->setExpectedException( '\SMW\Exception\FileNotFoundException' );
+ new CsvFileIterator( 'Foo' );
+ }
+
+ public function testForEachOnCsvFileWithNoHeader() {
+
+ $sample = [
+ '1,Foo,abc',
+ '2,Bar,123'
+ ];
+
+ $this->tempFile->write( $this->file, implode( "\n", $sample ) );
+
+ $instance = new CsvFileIterator(
+ $this->file,
+ false,
+ ','
+ );
+
+ $res = [];
+
+ foreach ( $instance as $row ) {
+ $res[] = $row;
+ }
+
+ $this->assertEmpty(
+ $instance->getHeader()
+ );
+
+ $this->assertEquals(
+ $res,
+ [
+ [ '1', 'Foo', 'abc' ],
+ [ '2', 'Bar', '123' ]
+ ]
+ );
+ }
+
+ public function testForEachOnCsvFileWithHeader() {
+
+ $sample = [
+ 'No,Text,Other',
+ '1,Foo,abc',
+ '2,Bar,123'
+ ];
+
+ $this->tempFile->write( $this->file, implode( "\n", $sample ) );
+
+ $instance = new CsvFileIterator(
+ $this->file,
+ true,
+ ','
+ );
+
+ $res = [];
+
+ foreach ( $instance as $row ) {
+ $res[] = $row;
+ }
+
+ $this->assertEquals(
+ $instance->getHeader(),
+ [
+ 'No',
+ 'Text',
+ 'Other'
+ ]
+ );
+
+ $this->assertEquals(
+ $res,
+ [
+ [ '1', 'Foo', 'abc' ],
+ [ '2', 'Bar', '123' ]
+ ]
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/MappingIteratorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/MappingIteratorTest.php
new file mode 100644
index 00000000..f8ad4783
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/MappingIteratorTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Iterators;
+
+use ArrayIterator;
+use SMW\Iterators\MappingIterator;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Iterators\MappingIterator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class MappingIteratorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ MappingIterator::class,
+ new MappingIterator( [], function() {
+ } )
+ );
+ }
+
+ public function testInvalidConstructorArgumentThrowsException() {
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance = new MappingIterator( 2, function() {
+ } );
+ }
+
+ public function testdoIterateOnArray() {
+
+ $expected = [
+ 1 , 42
+ ];
+
+ $mappingIterator = new MappingIterator( $expected, function( $counter ) {
+ return $counter;
+ } );
+
+ foreach ( $mappingIterator as $key => $value ) {
+ $this->assertEquals(
+ $expected[$key],
+ $value
+ );
+ }
+ }
+
+ public function testdoIterateOnArrayIterator() {
+
+ $expected = [
+ 1001 , 42
+ ];
+
+ $mappingIterator = new MappingIterator( new ArrayIterator( $expected ), function( $counter ) {
+ return $counter;
+ } );
+
+ $this->assertCount(
+ 2,
+ $mappingIterator
+ );
+
+ foreach ( $mappingIterator as $key => $value ) {
+ $this->assertEquals(
+ $expected[$key],
+ $value
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ResultIteratorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ResultIteratorTest.php
new file mode 100644
index 00000000..bd56e345
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Iterators/ResultIteratorTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace SMW\Tests\Iterators;
+
+use SMW\Iterators\ResultIterator;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Iterators\ResultIterator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ResultIteratorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ResultIterator::class,
+ new ResultIterator( [] )
+ );
+ }
+
+ public function testInvalidConstructorArgumentThrowsException() {
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance = new ResultIterator( 2 );
+ }
+
+ public function testdoIterateOnArray() {
+
+ $result = [
+ 1, 42
+ ];
+
+ $instance = new ResultIterator( $result );
+
+ $this->assertCount(
+ 2,
+ $instance
+ );
+
+ foreach ( $instance as $key => $value ) {
+ $this->assertEquals(
+ $result[$key],
+ $value
+ );
+ }
+ }
+
+ public function testdoSeekOnArray() {
+
+ $result = [
+ 1, 42, 1001
+ ];
+
+ $instance = new ResultIterator( $result );
+ $instance->seek( 1 );
+
+ $this->assertEquals(
+ 42,
+ $instance->current()
+ );
+ }
+
+ public function testdoIterateOnResultWrapper() {
+
+ $resultWrapper = $this->getMockBuilder( '\ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resultWrapper->expects( $this->once() )
+ ->method( 'numRows' )
+ ->will( $this->returnValue( 1 ) );
+
+ $resultWrapper->expects( $this->atLeastOnce() )
+ ->method( 'current' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new ResultIterator( $resultWrapper );
+
+ $this->assertCount(
+ 1,
+ $instance
+ );
+
+ foreach ( $instance as $key => $value ) {
+ $this->assertEquals(
+ 42,
+ $value
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/FallbackFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/FallbackFinderTest.php
new file mode 100644
index 00000000..824eeb79
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/FallbackFinderTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests\Lang;
+
+use SMW\Lang\FallbackFinder;
+use SMW\Lang\JsonContentsFileReader;
+
+/**
+ * @covers \SMW\Lang\FallbackFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FallbackFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $jsonContentsFileReader;
+
+ protected function setUp() {
+
+ $this->jsonContentsFileReader = $this->getMockBuilder( JsonContentsFileReader::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FallbackFinder::class,
+ new FallbackFinder( $this->jsonContentsFileReader )
+ );
+ }
+
+ public function testGetDefaultFallbackLanguage() {
+
+ $this->jsonContentsFileReader->expects( $this->never() )
+ ->method( 'readByLanguageCode' );
+
+ $instance = new FallbackFinder(
+ $this->jsonContentsFileReader
+ );
+
+ $this->assertEquals(
+ 'en',
+ $instance->getFallbackLanguageBy( '' )
+ );
+
+ $this->assertEquals(
+ $instance->getCanonicalFallbackLanguageCode(),
+ $instance->getFallbackLanguageBy()
+ );
+ }
+
+ public function testgetFallbackLanguageByStatedFallback() {
+
+ $mockedContent = [
+ 'fallback_language' => 'Foo'
+ ];
+
+ $this->jsonContentsFileReader->expects( $this->atLeastOnce() )
+ ->method( 'readByLanguageCode' )
+ ->will( $this->returnValue( $mockedContent ) );
+
+ $instance = new FallbackFinder(
+ $this->jsonContentsFileReader
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getFallbackLanguageBy( 'unknownLanguageCode' )
+ );
+ }
+
+ public function testgetFallbackLanguageByUnknownLanguageCode() {
+
+ $this->jsonContentsFileReader->expects( $this->atLeastOnce() )
+ ->method( 'readByLanguageCode' )
+ ->will( $this->throwException( new \RuntimeException ) );
+
+ $instance = new FallbackFinder(
+ $this->jsonContentsFileReader
+ );
+
+ $this->assertEquals(
+ 'en',
+ $instance->getFallbackLanguageBy( 'unknownLanguageCode' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/JsonContentsFileReaderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/JsonContentsFileReaderTest.php
new file mode 100644
index 00000000..db42b246
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/JsonContentsFileReaderTest.php
@@ -0,0 +1,173 @@
+<?php
+
+namespace SMW\Tests\Lang;
+
+use SMW\Lang\JsonContentsFileReader;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Lang\JsonContentsFileReader
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class JsonContentsFileReaderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ JsonContentsFileReader::class,
+ new JsonContentsFileReader()
+ );
+ }
+
+ /**
+ * @dataProvider languageCodeProvider
+ */
+ public function testReadByLanguageCode( $languageCode ) {
+
+ $instance = new JsonContentsFileReader();
+
+ $this->assertInternalType(
+ 'array',
+ $instance->readByLanguageCode( $languageCode )
+ );
+ }
+
+ /**
+ * @dataProvider languageCodeProvider
+ */
+ public function testReadByLanguageCodeWithCache( $languageCode ) {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( true ) );
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new JsonContentsFileReader( $cache );
+ $instance->clear();
+
+ $this->assertInternalType(
+ 'array',
+ $instance->readByLanguageCode( $languageCode )
+ );
+ }
+
+ public function testReadByLanguageCodeToUseInMemoryCache() {
+
+ $instance = $this->getMockBuilder( JsonContentsFileReader::class )
+ ->setMethods( [ 'readJSONFile', 'getFileModificationTime' ] )
+ ->getMock();
+
+ $instance->expects( $this->once() )
+ ->method( 'readJSONFile' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance->expects( $this->once() )
+ ->method( 'getFileModificationTime' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance->readByLanguageCode( 'foo' );
+
+ // InMemory use
+ $instance->readByLanguageCode( 'foo' );
+ }
+
+ public function testReadByLanguageCodeIsForcedToRereadFromFile() {
+
+ $instance = $this->getMockBuilder( JsonContentsFileReader::class )
+ ->setMethods( [ 'readJSONFile', 'getFileModificationTime' ] )
+ ->getMock();
+
+ $instance->expects( $this->exactly( 2 ) )
+ ->method( 'readJSONFile' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance->expects( $this->exactly( 2 ) )
+ ->method( 'getFileModificationTime' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance->readByLanguageCode( 'bar' );
+ $instance->readByLanguageCode( 'bar', true );
+ }
+
+ public function testTryToReadInaccessibleFileByLanguageThrowsException() {
+
+ $instance = new JsonContentsFileReader();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->readByLanguageCode( 'foo', true );
+ }
+
+ /**
+ * This method is just for convenience so that one can quickly add contents to files
+ * without requiring an extra class when extending the language content. Normally the
+ * test in active
+ *
+ * @dataProvider dataExtensionProvider
+ */
+ public function WriteToFile( $topic, $extension ) {
+
+ $instance = new JsonContentsFileReader();
+ $list ='ar,arz,ca,de,es,fi,fr,he,hu,id,it,nb,nl,pl,pt,ru,sk,zh-cn,zh-tw';
+
+ foreach ( explode( ',', $list ) as $lang ) {
+ $contents = $instance->readByLanguageCode( $lang, true );
+
+ if ( $contents === '' || !isset( $contents[$topic] ) ) {
+ continue;
+ }
+
+ $contents[$topic] = $contents[$topic] + $extension;
+
+ $instance->writeByLanguageCode( $lang, $contents );
+ }
+ }
+
+ /**
+ * @dataProvider languageCodeProvider
+ */
+ public function testgetFileModificationTime( $languageCode ) {
+
+ $instance = new JsonContentsFileReader();
+
+ $this->assertInternalType(
+ 'integer',
+ $instance->getFileModificationTime( $languageCode )
+ );
+ }
+
+ public function languageCodeProvider() {
+
+ $provider[] = [
+ 'en'
+ ];
+
+ return $provider;
+ }
+
+ public function dataExtensionProvider() {
+
+ $provider[] = [
+ 'dataTypeLabels',
+ [
+ "_ref_rec" => "Reference"
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LangTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LangTest.php
new file mode 100644
index 00000000..b1330d29
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LangTest.php
@@ -0,0 +1,320 @@
+<?php
+
+namespace SMW\Tests\Lang;
+
+use SMW\Lang\Lang;
+use SMW\Lang\LanguageContents;
+
+/**
+ * @covers \SMW\Lang\Lang
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class LangTest extends \PHPUnit_Framework_TestCase {
+
+ private $languageContents;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->languageContents = $this->getMockBuilder( LanguageContents::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function tearDown() {
+ Lang::clear();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Lang::class,
+ new Lang( $this->languageContents )
+ );
+
+ $this->assertInstanceOf(
+ Lang::class,
+ Lang::getInstance()
+ );
+
+ Lang::clear();
+ }
+
+ public function testGetNamespaces() {
+
+ $contents = [
+ "SMW_NS_PROPERTY" => "Property"
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'namespace.labels' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ [ SMW_NS_PROPERTY => "Property" ],
+ $instance->getNamespaces()
+ );
+ }
+
+ public function testGetNamespaceAliases() {
+
+ $contents = [
+ "Property" => "SMW_NS_PROPERTY"
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'namespace.aliases' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ [ "Property" => SMW_NS_PROPERTY ],
+ $instance->getNamespaceAliases()
+ );
+ }
+
+ public function testGetPreferredDateFormatByPrecisionOnMatchedPrecision() {
+
+ $contents = [
+ "SMW_PREC_YMDT" => "d m Y"
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'date.precision' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ 'd m Y',
+ $instance->getPreferredDateFormatByPrecision( SMW_PREC_YMDT )
+ );
+ }
+
+ public function testGetPreferredDateFormatOnNotMatchablePrecision() {
+
+ $contents = [
+ "Foo" => "d m Y"
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'date.precision' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ 'd F Y H:i:s',
+ $instance->getPreferredDateFormatByPrecision( SMW_PREC_YMDT )
+ );
+ }
+
+ public function testGetDatatypeLabels() {
+
+ $contents = [
+ "Foo" => "Bar"
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'datatype.labels' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ [ "Foo" => 'Bar' ],
+ $instance->getDatatypeLabels()
+ );
+ }
+
+ public function testFindDatatypeByLabel() {
+
+ $contents = [
+ "Bar" => "_foo"
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ '_foo',
+ $instance->findDatatypeByLabel( 'Bar' )
+ );
+ }
+
+ public function testGetPropertyIdByLabel() {
+
+ $this->languageContents->expects( $this->at( 0 ) )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'property.labels' ),
+ $this->anything() )
+ ->will( $this->returnValue( [ "_FOO" => "Foo" ] ) );
+
+ $this->languageContents->expects( $this->at( 1 ) )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'datatype.labels' ),
+ $this->anything() )
+ ->will( $this->returnValue( [] ) );
+
+ $this->languageContents->expects( $this->at( 2 ) )
+ ->method( 'get' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->languageContents->expects( $this->at( 3 ) )
+ ->method( 'get' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ '_FOO',
+ $instance->getPropertyIdByLabel( 'Foo' )
+ );
+ }
+
+ public function testGetPropertyLabelList() {
+
+ $propertyLabels = [
+ '_Foo' => 'Bar',
+ '_Foo2' => 'Baar',
+ '_Foo3' => 'Abc'
+ ];
+
+ $this->languageContents->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->onConsecutiveCalls( $propertyLabels, [], [], [] ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $instance->fetch( 'foo' );
+
+ $this->assertEquals(
+ [ 'label' => [
+ 'Bar' => '_Foo',
+ 'Baar' => '_Foo2',
+ 'Abc' => '_Foo3'
+ ] ],
+ $instance->getPropertyLabelList()
+ );
+ }
+
+ public function testGetDateFormats() {
+
+ $contents = [
+ [ 'SMW_Y' ],
+ [ 'SMW_MY', 'SMW_YM' ]
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'date.format' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ [ [ 9 ], [ 97, 76 ] ],
+ $instance->getDateFormats()
+ );
+ }
+
+ public function testFindMonthNumberByLabelWithCaseInsensitiveSearch() {
+
+ $contents = [
+ [ 'January', 'Jan' ],
+ [ 'February', 'Feb' ],
+ [ 'March', 'Mar' ]
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'date.months' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ 3,
+ $instance->findMonthNumberByLabel( 'mar' )
+ );
+ }
+
+ public function testGetMonthLabelByNumber() {
+
+ $contents = [
+ [ 'January', 'Jan' ],
+ [ 'February', 'Feb' ],
+ [ 'March', 'Mar' ]
+ ];
+
+ $this->languageContents->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->with(
+ $this->equalTo( 'date.months' ),
+ $this->anything() )
+ ->will( $this->returnValue( $contents ) );
+
+ $instance = new Lang(
+ $this->languageContents
+ );
+
+ $this->assertEquals(
+ 'March',
+ $instance->getMonthLabelByNumber( 3 )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LanguageContentsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LanguageContentsTest.php
new file mode 100644
index 00000000..285205ff
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Lang/LanguageContentsTest.php
@@ -0,0 +1,204 @@
+<?php
+
+namespace SMW\Tests\Lang;
+
+use SMW\Lang\FallbackFinder;
+use SMW\Lang\JsonContentsFileReader;
+use SMW\Lang\LanguageContents;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Lang\LanguageContents
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class LanguageContentsTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $jsonContentsFileReader;
+ private $fallbackFinder;
+
+ protected function setUp() {
+
+ $this->jsonContentsFileReader = $this->getMockBuilder( JsonContentsFileReader::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->fallbackFinder = $this->getMockBuilder( FallbackFinder::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ LanguageContents::class,
+ new LanguageContents( $this->jsonContentsFileReader, $this->fallbackFinder )
+ );
+ }
+
+ public function testGetCanonicalFallbackLanguageCode() {
+
+ $this->fallbackFinder->expects( $this->atLeastOnce() )
+ ->method( 'getCanonicalFallbackLanguageCode' );
+
+ $instance = new LanguageContents(
+ $this->jsonContentsFileReader,
+ $this->fallbackFinder
+ );
+
+ $instance->getCanonicalFallbackLanguageCode();
+ }
+
+ public function testPrepareWithLanguageWithoutFallback() {
+
+ $languageCode = 'Foo';
+
+ $this->jsonContentsFileReader->expects( $this->atLeastOnce() )
+ ->method( 'canReadByLanguageCode' )
+ ->will( $this->returnValue( true ) );
+
+ $this->jsonContentsFileReader->expects( $this->atLeastOnce() )
+ ->method( 'readByLanguageCode' )
+ ->with( $this->equalTo( $languageCode ) );
+
+ $instance = new LanguageContents(
+ $this->jsonContentsFileReader,
+ $this->fallbackFinder
+ );
+
+ $this->assertFalse(
+ $instance->isLoaded( $languageCode )
+ );
+
+ $instance->load( $languageCode );
+
+ $this->assertTrue(
+ $instance->isLoaded( $languageCode )
+ );
+ }
+
+ public function testGetContentsByLanguage_ID_Depth_2() {
+
+ $languageCode = 'Foo';
+
+ $this->jsonContentsFileReader->expects( $this->at( 0 ) )
+ ->method( 'readByLanguageCode' )
+ ->with( $this->equalTo( $languageCode ) )
+ ->will( $this->returnValue( [ 'Foo' => [ 'Bar' => 123 ] ] ) );
+
+ $this->fallbackFinder->expects( $this->atLeastOnce() )
+ ->method( 'getCanonicalFallbackLanguageCode' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $instance = new LanguageContents(
+ $this->jsonContentsFileReader,
+ $this->fallbackFinder
+ );
+
+ $this->assertEquals(
+ 123,
+ $instance->get( 'Foo.Bar', $languageCode )
+ );
+ }
+
+ public function testGetContentsByLanguage_ID_Depth_3() {
+
+ $languageCode = 'Foo';
+
+ $this->jsonContentsFileReader->expects( $this->at( 0 ) )
+ ->method( 'readByLanguageCode' )
+ ->with( $this->equalTo( $languageCode ) )
+ ->will( $this->returnValue( [ 'Foo' => [ 'Bar' => [ 'Foobar' => 456 ] ] ] ) );
+
+ $this->fallbackFinder->expects( $this->atLeastOnce() )
+ ->method( 'getCanonicalFallbackLanguageCode' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $instance = new LanguageContents(
+ $this->jsonContentsFileReader,
+ $this->fallbackFinder
+ );
+
+ $this->assertEquals(
+ 456,
+ $instance->get( 'Foo.Bar.Foobar', $languageCode )
+ );
+ }
+
+ public function testGetContentsByLanguageWithIndexWithFallback() {
+
+ $languageCode = 'Foo';
+ $fallback = 'Foobar';
+
+ $this->jsonContentsFileReader->expects( $this->at( 0 ) )
+ ->method( 'readByLanguageCode' )
+ ->with( $this->equalTo( $languageCode ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->jsonContentsFileReader->expects( $this->at( 1 ) )
+ ->method( 'readByLanguageCode' )
+ ->with( $this->equalTo( $fallback ) )
+ ->will( $this->returnValue( [ 'Bar' => 123 ] ) );
+
+ $this->fallbackFinder->expects( $this->atLeastOnce() )
+ ->method( 'getCanonicalFallbackLanguageCode' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $this->fallbackFinder->expects( $this->at( 1 ) )
+ ->method( 'getFallbackLanguageBy' )
+ ->will( $this->returnValue( $fallback ) );
+
+ $instance = new LanguageContents(
+ $this->jsonContentsFileReader,
+ $this->fallbackFinder
+ );
+
+ $this->assertEquals(
+ 123,
+ $instance->get( 'Bar', $languageCode )
+ );
+ }
+
+ public function testGetContentsByLanguageWithIndexWithFallbackButMissingIndexThrowsException() {
+
+ $languageCode = 'Foo';
+ $fallback = 'Foobar';
+
+ $this->jsonContentsFileReader->expects( $this->at( 0 ) )
+ ->method( 'readByLanguageCode' )
+ ->with( $this->equalTo( $languageCode ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->jsonContentsFileReader->expects( $this->at( 1 ) )
+ ->method( 'readByLanguageCode' )
+ ->with( $this->equalTo( $fallback ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->fallbackFinder->expects( $this->atLeastOnce() )
+ ->method( 'getCanonicalFallbackLanguageCode' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $this->fallbackFinder->expects( $this->at( 1 ) )
+ ->method( 'getFallbackLanguageBy' )
+ ->will( $this->returnValue( $fallback ) );
+
+ $this->fallbackFinder->expects( $this->at( 3 ) )
+ ->method( 'getFallbackLanguageBy' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $instance = new LanguageContents(
+ $this->jsonContentsFileReader,
+ $this->fallbackFinder
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->get( 'Bar', $languageCode );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/LocalizerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/LocalizerTest.php
new file mode 100644
index 00000000..9b0b7e16
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/LocalizerTest.php
@@ -0,0 +1,372 @@
+<?php
+
+namespace SMW\Tests;
+
+use Language;
+use SMW\Localizer;
+
+/**
+ * @covers \SMW\Localizer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class LocalizerTest extends \PHPUnit_Framework_TestCase {
+
+ protected function tearDown() {
+ Localizer::clear();
+ }
+
+ public function testCanConstruct() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Localizer',
+ new Localizer( $language )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Localizer',
+ Localizer::getInstance()
+ );
+ }
+
+ public function testGetContentLanguage() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Localizer( $language );
+
+ $this->assertSame(
+ $language,
+ $instance->getContentLanguage()
+ );
+
+ $this->assertSame(
+ $GLOBALS['wgContLang'],
+ Localizer::getInstance()->getContentLanguage()
+ );
+ }
+
+ public function testNamespaceTextById() {
+
+ $instance = new Localizer( Language::factory( 'en') );
+
+ $this->assertEquals(
+ 'Property',
+ $instance->getNamespaceTextById( SMW_NS_PROPERTY )
+ );
+ }
+
+ public function testNamespaceIndexByName() {
+
+ $instance = new Localizer( Language::factory( 'en') );
+
+ $this->assertEquals(
+ SMW_NS_PROPERTY,
+ $instance->getNamespaceIndexByName( 'property' )
+ );
+ }
+
+ public function testSupportedLanguageForLowerCaseLetter() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( 'Skipping because `Language::isKnownLanguageTag` is not supported on 1.19' );
+ }
+
+ $this->assertTrue(
+ Localizer::isKnownLanguageTag( 'en' )
+ );
+ }
+
+ public function testSupportedLanguageForUpperCaseLetter() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( 'Skipping because `Language::isKnownLanguageTag` is not supported on 1.19' );
+ }
+
+ $this->assertTrue(
+ Localizer::isKnownLanguageTag( 'ZH-HANS' )
+ );
+ }
+
+ public function testAsBCP47FormattedLanguageCode() {
+ $this->assertEquals(
+ 'zh-Hans',
+ Localizer::asBCP47FormattedLanguageCode( 'zh-hans' )
+ );
+ }
+
+ public function testCanGetAnnotatedLanguageCodeOnValidMarkedValue() {
+
+ $value = 'Foo@en';
+
+ $this->assertEquals(
+ 'en',
+ Localizer::getAnnotatedLanguageCodeFrom( $value )
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $value
+ );
+ }
+
+ public function testCanGetAnnotatedLanguageCodeOnDoubledMarkedValue() {
+
+ $value = 'Foo@@en';
+
+ $this->assertEquals(
+ 'en',
+ Localizer::getAnnotatedLanguageCodeFrom( $value )
+ );
+
+ $this->assertEquals(
+ 'Foo@',
+ $value
+ );
+ }
+
+ public function testCanGetAnnotatedLanguageCodeOnValueWithDash() {
+
+ $value = 'Foo@zh-Hans';
+
+ $this->assertEquals(
+ 'zh-Hans',
+ Localizer::getAnnotatedLanguageCodeFrom( $value )
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $value
+ );
+ }
+
+ public function testCanNotGetAnnotatedLanguageCodeThatContainsInvalidCharacter() {
+
+ $value = 'Foo@en#bar';
+
+ $this->assertFalse(
+ Localizer::getAnnotatedLanguageCodeFrom( $value )
+ );
+ }
+
+ public function testCanNotGetLanguageCodeOnNonMarkedValue() {
+
+ $value = 'Fooen';
+
+ $this->assertFalse(
+ Localizer::getLanguageCodeFrom( $value )
+ );
+
+ $this->assertEquals(
+ 'Fooen',
+ $value
+ );
+ }
+
+ public function testCanNotGetLanguageCodeOnMissingLanguageCode() {
+
+ $value = 'Foo@';
+
+ $this->assertFalse(
+ Localizer::getLanguageCodeFrom( $value )
+ );
+
+ $this->assertEquals(
+ 'Foo@',
+ $value
+ );
+ }
+
+ public function testGetLanguageCodeByRule_OnTitleExpectedToPageLanguage() {
+
+ $contentLanguage = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Localizer( $contentLanguage );
+
+ $pageLanguage = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $pageLanguage ) );
+
+ $this->assertEquals(
+ $pageLanguage,
+ $instance->getPreferredContentLanguage( $title )
+ );
+ }
+
+ public function testGetLanguageCodeByRule_OnNotProvidedTitlePageLanguageExpectedToReturnUserLanguage() {
+
+ $contentLanguage = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Localizer( $contentLanguage );
+
+ $this->assertEquals(
+ $instance->getContentLanguage(),
+ $instance->getPreferredContentLanguage( null )
+ );
+ }
+
+ public function testLang() {
+
+ $instance = Localizer::getInstance();
+
+ $this->assertInstanceOf(
+ '\SMW\Lang\Lang',
+ $instance->getLang()
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Lang\Lang',
+ $instance->getLang( 'en' )
+ );
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->once() )
+ ->method( 'getCode' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $this->assertInstanceOf(
+ '\SMW\Lang\Lang',
+ $instance->getLang( $language )
+ );
+ }
+
+ public function testConvertDoubleWidth() {
+
+ $this->assertEquals(
+ '2000',
+ Localizer::convertDoubleWidth( 'ï¼’ï¼ï¼ï¼' )
+ );
+
+ $this->assertEquals(
+ 'aBc',
+ Localizer::getInstance()->convertDoubleWidth( 'ï½ï¼¢ï½ƒ' )
+ );
+ }
+
+ public function testCreateTextWithNamespacePrefix() {
+
+ $instance = new Localizer( Language::factory( 'en') );
+
+ $this->assertEquals(
+ 'Property:foo bar',
+ $instance->createTextWithNamespacePrefix( SMW_NS_PROPERTY, 'foo bar' )
+ );
+ }
+
+ public function testGetCanonicalizedUrlByNamespace() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->exactly( 3 ) )
+ ->method( 'getNsText' )
+ ->will( $this->returnValue( 'Spécial' ) );
+
+ $instance = new Localizer( $language );
+
+ $this->assertEquals(
+ 'http://example.org/wiki/Special:URIResolver/Property-3AHas_query',
+ $instance->getCanonicalizedUrlByNamespace( NS_SPECIAL, 'http://example.org/wiki/Sp%C3%A9cial:URIResolver/Property-3AHas_query' )
+ );
+
+ $this->assertEquals(
+ 'http://example.org/wiki/Special:URIResolver/Property-3AHas_query',
+ $instance->getCanonicalizedUrlByNamespace( NS_SPECIAL, 'http://example.org/wiki/Spécial:URIResolver/Property-3AHas_query' )
+ );
+
+ $this->assertEquals(
+ 'http://example.org/index.php?title=Special:URIResolver&Property-3AHas_query',
+ $instance->getCanonicalizedUrlByNamespace( NS_SPECIAL, 'http://example.org/index.php?title=Spécial:URIResolver&Property-3AHas_query' )
+ );
+ }
+
+ public function testGetCanonicalName() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Localizer( $language );
+
+ $this->assertEquals(
+ 'Property',
+ $instance->getCanonicalNamespaceTextById( SMW_NS_PROPERTY )
+ );
+
+ $this->assertEquals(
+ 'Help',
+ $instance->getCanonicalNamespaceTextById( NS_HELP )
+ );
+ }
+
+ public function testHasLocalTimeOffsetPreference() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( 'smw-prefs-general-options-time-correction' ) )
+ ->will( $this->returnValue( true ) );
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Localizer( $language );
+
+ $this->assertTrue(
+ $instance->hasLocalTimeOffsetPreference( $user )
+ );
+ }
+
+ public function testGetLocalTime() {
+
+ $dataTime = $this->getMockBuilder( '\DateTime' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Localizer( $language );
+
+ $this->assertInstanceOf(
+ 'DateTime',
+ $instance->getLocalTime( $dataTime, $user )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ConceptCacheRebuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ConceptCacheRebuilderTest.php
new file mode 100644
index 00000000..0751d743
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ConceptCacheRebuilderTest.php
@@ -0,0 +1,224 @@
+<?php
+
+namespace SMW\Tests\Maintenance;
+
+use SMW\DIConcept;
+use SMW\Maintenance\ConceptCacheRebuilder;
+
+/**
+ * @covers \SMW\Maintenance\ConceptCacheRebuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class ConceptCacheRebuilderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockForAbstractClass( '\SMW\Store' );
+
+ $settings = $this->getMockBuilder( '\SMW\Settings' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\ConceptCacheRebuilder',
+ new ConceptCacheRebuilder( $store, $settings )
+ );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testRebuildWithoutOptionsAndActions() {
+
+ $store = $this->getMockForAbstractClass( '\SMW\Store' );
+
+ $settings = $this->getMockBuilder( '\SMW\Settings' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ConceptCacheRebuilder(
+ $store,
+ $settings
+ );
+
+ $this->assertFalse( $instance->rebuild() );
+ }
+
+ /**
+ * @dataProvider actionProvider
+ */
+ public function testRebuildFullConceptWithoutRangeSelectionOnMockStore( $action ) {
+
+ $concept = new DIConcept( 'Foo', '', '', '', '' );
+
+ $concept->setCacheStatus( 'full' );
+ $concept->setCacheDate( '1358515326' );
+ $concept->setCacheCount( '1000' );
+
+ $instance = $this->acquireInstanceFor( $concept );
+
+ $instance->setParameters( [
+ $action => true
+ ] );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @dataProvider actionProvider
+ */
+ public function testRebuildEmptyConceptWithoutRangeSelectionOnMockStore( $action ) {
+
+ $concept = new DIConcept( 'Foo', '', '', '', '' );
+ $concept->setCacheStatus( 'empty' );
+
+ $instance = $this->acquireInstanceFor( $concept );
+
+ $instance->setParameters( [
+ $action => true
+ ] );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @dataProvider actionProvider
+ */
+ public function testRebuildFullConceptWithRangeSelectionOnMockStore( $action ) {
+
+ $concept = new DIConcept( 'Foo', '', '', '', '' );
+
+ $concept->setCacheStatus( 'full' );
+ $concept->setCacheDate( '1358515326' );
+ $concept->setCacheCount( '1000' );
+
+ $instance = $this->acquireInstanceFor( $concept );
+
+ $instance->setParameters( [
+ $action => true,
+ 's' => 0,
+ 'e' => 90000
+ ] );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @dataProvider actionProvider
+ */
+ public function testRebuildSingleEmptyConceptWithRangeSelectionOnMockStore( $action ) {
+
+ $concept = new DIConcept( 'Foo', '', '', '', '' );
+ $concept->setCacheStatus( 'empty' );
+
+ $instance = $this->acquireInstanceFor( $concept );
+
+ $instance->setParameters( [
+ $action => true,
+ 's' => 0,
+ 'e' => 90000
+ ] );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @dataProvider actionProvider
+ */
+ public function testRebuildSingleFullConceptOnMockStore( $action ) {
+
+ $concept = new DIConcept( 'Foo', '', '', '', '' );
+
+ $concept->setCacheStatus( 'full' );
+ $concept->setCacheDate( '1358515326' );
+ $concept->setCacheCount( '1000' );
+
+ $instance = $this->acquireInstanceFor( $concept );
+
+ $instance->setParameters( [
+ $action => true,
+ 'old' => 10,
+ 'concept' => 'Bar'
+ ] );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @dataProvider actionProvider
+ */
+ public function testRebuildWithNullConceptOnMockStore( $action ) {
+
+ $instance = $this->acquireInstanceFor( null );
+
+ $instance->setParameters( [
+ $action => true,
+ 'concept' => 'Bar'
+ ] );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ private function acquireInstanceFor( $concept = null ) {
+
+ $expectedToRun = $concept !== null ? $this->any() : $this->never();
+ $refreshConceptCacheReturn = $concept !== null ? $concept->getConceptQuery() : null;
+
+ $row = new \stdClass;
+ $row->page_namespace = 0;
+ $row->page_title = 1;
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $expectedToRun )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $store = $this->getMockBuilder( 'SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConceptCacheStatus' )
+ ->will( $this->returnValue( $concept ) );
+
+ $store->expects( $expectedToRun )
+ ->method( 'refreshConceptCache' )
+ ->will( $this->returnValue( [ $refreshConceptCacheReturn ] ) );
+
+ $store->expects( $expectedToRun )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $settings = $this->getMockBuilder( '\SMW\Settings' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ConceptCacheRebuilder(
+ $store,
+ $settings
+ );
+
+ $instance->setParameters( [
+ 'quiet' => true,
+ ] );
+
+ return $instance;
+ }
+
+ public function actionProvider() {
+ return [
+ [ 'status' ],
+ [ 'create' ],
+ [ 'delete' ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DataRebuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DataRebuilderTest.php
new file mode 100644
index 00000000..a3b3a441
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DataRebuilderTest.php
@@ -0,0 +1,420 @@
+<?php
+
+namespace SMW\Tests\Maintenance;
+
+use SMW\Maintenance\DataRebuilder;
+use SMW\Options;
+use Title;
+use SMW\Tests\PHPUnitCompat;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Maintenance\DataRebuilder
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class DataRebuilderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ protected $obLevel;
+ private $connectionManager;
+ private $testEnvironment;
+
+ // The Store writes to the output buffer during drop/setupStore, to avoid
+ // inappropriate buffer settings which can cause interference during unit
+ // testing, we clean the output buffer
+ protected function setUp() {
+
+ $nullJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\NullJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'newUpdateJob' ] )
+ ->getMock();
+
+ $jobFactory->expects( $this->any() )
+ ->method( 'newUpdateJob' )
+ ->will( $this->returnValue( $nullJob ) );
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->obLevel = ob_get_level();
+ ob_start();
+
+ parent::setUp();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ $this->testEnvironment->tearDown();
+
+ while ( ob_get_level() > $this->obLevel ) {
+ ob_end_clean();
+ }
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\DataRebuilder',
+ new DataRebuilder( $store, $titleFactory )
+ );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testRebuildAllWithoutOptions() {
+
+ $entityRebuildDispatcher = $this->getMockBuilder( '\SMW\SQLStore\EntityRebuildDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityRebuildDispatcher->expects( $this->once() )
+ ->method( 'rebuild' )
+ ->will( $this->returnCallback( [ $this, 'refreshDataOnMockCallback' ] ) );
+
+ $entityRebuildDispatcher->expects( $this->any() )
+ ->method( 'getMaxId' )
+ ->will( $this->returnValue( 1000 ) );
+
+ $entityRebuildDispatcher->expects( $this->any() )
+ ->method( 'getDispatchedEntities' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'refreshData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'refreshData' )
+ ->will( $this->returnValue( $entityRebuildDispatcher ) );
+
+ $store->setConnectionManager( $this->connectionManager );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataRebuilder( $store, $titleFactory );
+
+ // Needs an end otherwise phpunit is caught up in an infinite loop
+ $instance->setOptions( new Options( [
+ 'e' => 1
+ ] ) );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testRebuildAllWithFullDelete() {
+
+ $entityRebuildDispatcher = $this->getMockBuilder( '\SMW\SQLStore\EntityRebuildDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityRebuildDispatcher->expects( $this->atLeastOnce() )
+ ->method( 'rebuild' )
+ ->will( $this->returnCallback( [ $this, 'refreshDataOnMockCallback' ] ) );
+
+ $entityRebuildDispatcher->expects( $this->any() )
+ ->method( 'getMaxId' )
+ ->will( $this->returnValue( 1000 ) );
+
+ $entityRebuildDispatcher->expects( $this->any() )
+ ->method( 'getDispatchedEntities' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [
+ 'refreshData',
+ 'drop' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'refreshData' )
+ ->will( $this->returnValue( $entityRebuildDispatcher ) );
+
+ $store->expects( $this->once() )
+ ->method( 'drop' );
+
+ $store->setConnectionManager( $this->connectionManager );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataRebuilder( $store, $titleFactory );
+
+ $instance->setOptions( new Options( [
+ 'e' => 1,
+ 'f' => true,
+ 'verbose' => false
+ ] ) );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testRebuildAllWithStopRangeOption() {
+
+ $entityRebuildDispatcher = $this->getMockBuilder( '\SMW\SQLStore\EntityRebuildDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityRebuildDispatcher->expects( $this->exactly( 6 ) )
+ ->method( 'rebuild' )
+ ->will( $this->returnCallback( [ $this, 'refreshDataOnMockCallback' ] ) );
+
+ $entityRebuildDispatcher->expects( $this->any() )
+ ->method( 'getMaxId' )
+ ->will( $this->returnValue( 1000 ) );
+
+ $entityRebuildDispatcher->expects( $this->any() )
+ ->method( 'getDispatchedEntities' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'refreshData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'refreshData' )
+ ->will( $this->returnValue( $entityRebuildDispatcher ) );
+
+ $store->setConnectionManager( $this->connectionManager );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataRebuilder( $store, $titleFactory );
+
+ $instance->setOptions( new Options( [
+ 's' => 2,
+ 'n' => 5,
+ 'verbose' => false
+ ] ) );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testRebuildSelectedPagesWithQueryOption() {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( Title::newFromText( __METHOD__ ) ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [ $subject ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->at( 0 ) )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( 1 ) );
+
+ $store->expects( $this->at( 1 ) )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $store->setConnectionManager( $this->connectionManager );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataRebuilder( $store, $titleFactory );
+
+ $instance->setOptions( new Options( [
+ 'query' => '[[Category:Foo]]'
+ ] ) );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ public function testRebuildSelectedPagesWithCategoryNamespaceFilter() {
+
+ $row = new \stdClass;
+ $row->cat_title = 'Foo';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->stringContains( 'category' ),
+ $this->anything(),
+ $this->anything(),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataRebuilder( $store, $titleFactory );
+
+ $instance->setOptions( new Options( [
+ 'categories' => true
+ ] ) );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ public function testRebuildSelectedPagesWithPropertyNamespaceFilter() {
+
+ $row = new \stdClass;
+ $row->page_namespace = SMW_NS_PROPERTY;
+ $row->page_title = 'Bar';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'page_namespace' => SMW_NS_PROPERTY ] ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataRebuilder( $store, $titleFactory );
+
+ $instance->setOptions( new Options( [
+ 'p' => true
+ ] ) );
+
+ $this->assertTrue( $instance->rebuild() );
+ }
+
+ public function testRebuildSelectedPagesWithPageOption() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $titleFactory->expects( $this->at( 0 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Main page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Main page' ) ) );
+
+ $titleFactory->expects( $this->at( 1 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Some other page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Some other page' ) ) );
+
+ $titleFactory->expects( $this->at( 2 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Help:Main page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Main page', NS_HELP ) ) );
+
+ $titleFactory->expects( $this->at( 3 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Main page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Main page' ) ) );
+
+ $instance = new DataRebuilder( $store, $titleFactory );
+
+ $instance->setOptions( new Options( [
+ 'page' => 'Main page|Some other page|Help:Main page|Main page'
+ ] ) );
+
+ $this->assertTrue( $instance->rebuild() );
+
+ $this->assertEquals(
+ 3,
+ $instance->getRebuildCount()
+ );
+ }
+
+ /**
+ * @see Store::refreshData
+ */
+ public function refreshDataOnMockCallback( &$index ) {
+ $index++;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DistinctEntityDataRebuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DistinctEntityDataRebuilderTest.php
new file mode 100644
index 00000000..00962275
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DistinctEntityDataRebuilderTest.php
@@ -0,0 +1,290 @@
+<?php
+
+namespace SMW\Tests\Maintenance;
+
+use SMW\Maintenance\DistinctEntityDataRebuilder;
+use SMW\Options;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\Maintenance\DistinctEntityDataRebuilder
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DistinctEntityDataRebuilderTest extends \PHPUnit_Framework_TestCase {
+
+ protected $obLevel;
+ private $connectionManager;
+ private $testEnvironment;
+
+ // The Store writes to the output buffer during drop/setupStore, to avoid
+ // inappropriate buffer settings which can cause interference during unit
+ // testing, we clean the output buffer
+ protected function setUp() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->setOption( 'smwgSemanticsEnabled', true );
+ $store->setOption( 'smwgAutoRefreshSubject', true );
+
+ $this->testEnvironment = new TestEnvironment();
+ $spyLogger = $this->testEnvironment->newSpyLogger();
+
+ $store->setLogger( $spyLogger );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->obLevel = ob_get_level();
+ ob_start();
+
+ parent::setUp();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ $this->testEnvironment->tearDown();
+
+ while ( ob_get_level() > $this->obLevel ) {
+ ob_end_clean();
+ }
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\DistinctEntityDataRebuilder',
+ new DistinctEntityDataRebuilder( $store, $titleFactory )
+ );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testRebuildSelectedPagesWithQueryOption() {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( Title::newFromText( __METHOD__ ) ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [ $subject ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->at( 0 ) )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( 1 ) );
+
+ $store->expects( $this->at( 1 ) )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $store->setConnectionManager( $this->connectionManager );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DistinctEntityDataRebuilder(
+ $store,
+ $titleFactory
+ );
+
+ $instance->setOptions( new Options( [
+ 'query' => '[[Category:Foo]]'
+ ] ) );
+
+ $this->assertTrue(
+ $instance->doRebuild()
+ );
+ }
+
+ public function testRebuildSelectedPagesWithCategoryNamespaceFilter() {
+
+ $row = new \stdClass;
+ $row->cat_title = 'Foo';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->stringContains( 'category' ),
+ $this->anything(),
+ $this->anything(),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DistinctEntityDataRebuilder(
+ $store,
+ $titleFactory
+ );
+
+ $instance->setOptions( new Options( [
+ 'categories' => true
+ ] ) );
+
+ $this->assertTrue(
+ $instance->doRebuild()
+ );
+ }
+
+ public function testRebuildSelectedPagesWithPropertyNamespaceFilter() {
+
+ $row = new \stdClass;
+ $row->page_namespace = SMW_NS_PROPERTY;
+ $row->page_title = 'Bar';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'page_namespace' => SMW_NS_PROPERTY ] ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DistinctEntityDataRebuilder(
+ $store,
+ $titleFactory
+ );
+
+ $instance->setOptions( new Options( [
+ 'p' => true
+ ] ) );
+
+ $this->assertTrue(
+ $instance->doRebuild()
+ );
+ }
+
+ public function testRebuildSelectedPagesWithPageOption() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $titleFactory->expects( $this->at( 0 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Main page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Main page' ) ) );
+
+ $titleFactory->expects( $this->at( 1 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Some other page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Some other page' ) ) );
+
+ $titleFactory->expects( $this->at( 2 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Help:Main page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Main page', NS_HELP ) ) );
+
+ $titleFactory->expects( $this->at( 3 ) )
+ ->method( 'newFromText' )
+ ->with( $this->equalTo( 'Main page' ) )
+ ->will( $this->returnValue( Title::newFromText( 'Main page' ) ) );
+
+ $instance = new DistinctEntityDataRebuilder(
+ $store,
+ $titleFactory
+ );
+
+ $instance->setOptions( new Options( [
+ 'page' => 'Main page|Some other page|Help:Main page|Main page'
+ ] ) );
+
+ $this->assertTrue(
+ $instance->doRebuild()
+ );
+
+ $this->assertEquals(
+ 3,
+ $instance->getRebuildCount()
+ );
+ }
+
+ /**
+ * @see Store::refreshData
+ */
+ public function refreshDataOnMockCallback( &$index ) {
+ $index++;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DuplicateEntitiesDisposerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DuplicateEntitiesDisposerTest.php
new file mode 100644
index 00000000..b1f6cb10
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/DuplicateEntitiesDisposerTest.php
@@ -0,0 +1,187 @@
+<?php
+
+namespace SMW\Tests\Maintenance;
+
+use FakeResultWrapper;
+use SMW\Maintenance\DuplicateEntitiesDisposer;
+
+/**
+ * @covers \SMW\Maintenance\DuplicateEntitiesDisposer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DuplicateEntitiesDisposerTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $cache;
+ private $messageReporter;
+ private $connection;
+ private $propertyTableIdReferenceFinder;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyTableIdReferenceFinder = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableIdReferenceFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTableIdReferenceFinder' )
+ ->will( $this->returnValue( $this->propertyTableIdReferenceFinder ) );
+
+ $this->messageReporter = $this->getMockBuilder( '\Onoi\MessageReporter\MessageReporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ DuplicateEntitiesDisposer::class,
+ new DuplicateEntitiesDisposer( $this->store )
+ );
+ }
+
+ public function testFindDuplicateEntityRecords() {
+
+ $idTable = $this->getMockBuilder( '\stdClss' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'findDuplicates' ] )
+ ->getMock();
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $instance = new DuplicateEntitiesDisposer(
+ $this->store
+ );
+
+ $instance->findDuplicates();
+ }
+
+ public function testVerifyAndDispose_NoDuplicates() {
+
+ $this->store->expects( $this->never() )
+ ->method( 'getConnection' );
+
+ $instance = new DuplicateEntitiesDisposer(
+ $this->store
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $instance->verifyAndDispose( [] );
+ }
+
+ public function testVerifyAndDispose_NonIterable() {
+
+ $this->store->expects( $this->never() )
+ ->method( 'getConnection' );
+
+ $instance = new DuplicateEntitiesDisposer(
+ $this->store
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $instance->verifyAndDispose( 'Foo' );
+ }
+
+ public function testVerifyAndDispose_NoDuplicates_WithCache() {
+
+ $this->store->expects( $this->never() )
+ ->method( 'getConnection' );
+
+ $this->cache->expects( $this->atLeastOnce() )
+ ->method( 'delete' );
+
+ $instance = new DuplicateEntitiesDisposer(
+ $this->store,
+ $this->cache
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $instance->verifyAndDispose( [] );
+ }
+
+ public function testVerifyAndDispose_WithDuplicateRecord() {
+
+ $record = [
+ 'smw_title' => 'Foo',
+ 'smw_namespace' => 0,
+ 'smw_iw' => '',
+ 'smw_subobject' => ''
+ ];
+
+ $row = new \stdClass;
+ $row->smw_id = 42;
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( $record ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $idTable = $this->getMockBuilder( '\stdClss' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getDataItemById' ] )
+ ->getMock();
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->propertyTableIdReferenceFinder->expects( $this->atLeastOnce() )
+ ->method( 'hasResidualReferenceForId' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new DuplicateEntitiesDisposer(
+ $this->store
+ );
+
+ $instance->setMessageReporter(
+ $this->messageReporter
+ );
+
+ $duplicates = [
+ $record
+ ];
+
+ $instance->verifyAndDispose( $duplicates );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ExceptionFileLoggerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ExceptionFileLoggerTest.php
new file mode 100644
index 00000000..b64a75af
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/ExceptionFileLoggerTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\Maintenance\Jobs;
+
+use SMW\Maintenance\ExceptionFileLogger;
+use SMW\Options;
+
+/**
+ * @covers \SMW\Maintenance\ExceptionFileLogger
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class ExceptionFileLoggerTest extends \PHPUnit_Framework_TestCase {
+
+ private $file;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->file = $this->getMockBuilder( '\SMW\Utils\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ExceptionFileLogger::class,
+ new ExceptionFileLogger()
+ );
+ }
+
+ public function testGetter() {
+
+ $instance = new ExceptionFileLogger();
+
+ $instance->setOptions( new Options( [
+ 'exception-log' => __DIR__
+ ] ) );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->getExceptionFile()
+ );
+
+ $this->assertInternalType(
+ 'integer',
+ $instance->getExceptionCount()
+ );
+ }
+
+ public function testDoWriteExceptionLog() {
+
+ $this->file->expects( $this->once() )
+ ->method( 'write' );
+
+ $instance = new ExceptionFileLogger( 'foo', $this->file );
+
+ $instance->recordException(
+ 'Foo',
+ new \Exception( 'Bar' )
+ );
+
+ $this->assertEquals(
+ 1,
+ $instance->getExceptionCount()
+ );
+
+ $instance->doWrite();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceFactoryTest.php
new file mode 100644
index 00000000..936a9c65
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceFactoryTest.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace SMW\Tests\Maintenance\Jobs;
+
+use SMW\Maintenance\MaintenanceFactory;
+
+/**
+ * @covers \SMW\Maintenance\MaintenanceFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class MaintenanceFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\MaintenanceFactory',
+ new MaintenanceFactory()
+ );
+ }
+
+ public function testCanConstructMaintenanceHelper() {
+
+ $instance = new MaintenanceFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\MaintenanceHelper',
+ $instance->newMaintenanceHelper()
+ );
+ }
+
+ public function testCanConstructDataRebuilder() {
+
+ $instance = new MaintenanceFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\DataRebuilder',
+ $instance->newDataRebuilder( $this->store )
+ );
+ }
+
+ public function testCanConstructConceptCacheRebuilder() {
+
+ $instance = new MaintenanceFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\ConceptCacheRebuilder',
+ $instance->newConceptCacheRebuilder( $this->store )
+ );
+ }
+
+ public function testCanConstructPropertyStatisticsRebuilder() {
+
+ $instance = new MaintenanceFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\PropertyStatisticsRebuilder',
+ $instance->newPropertyStatisticsRebuilder( $this->store )
+ );
+ }
+
+ public function testCanConstructRebuildPropertyStatistics() {
+
+ $instance = new MaintenanceFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\RebuildPropertyStatistics',
+ $instance->newRebuildPropertyStatistics()
+ );
+ }
+
+ public function testCanConstructDuplicateEntitiesDisposer() {
+
+ $instance = new MaintenanceFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\DuplicateEntitiesDisposer',
+ $instance->newDuplicateEntitiesDisposer( $this->store )
+ );
+ }
+
+ public function testCanConstructMaintenanceLogger() {
+
+ $instance = new MaintenanceFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\MaintenanceLogger',
+ $instance->newMaintenanceLogger( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceHelperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceHelperTest.php
new file mode 100644
index 00000000..a4587621
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceHelperTest.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace SMW\Tests\Maintenance;
+
+use SMW\Maintenance\MaintenanceHelper;
+
+/**
+ * @covers \SMW\Maintenance\MaintenanceHelper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class MaintenanceHelperTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\MaintenanceHelper',
+ new MaintenanceHelper()
+ );
+ }
+
+ public function testSetGlobalForValidKey() {
+
+ $GLOBALS['FOObar'] = 42;
+
+ $instance = new MaintenanceHelper();
+ $instance->setGlobalToValue( 'FOObar', 99 );
+
+ $this->assertEquals(
+ $GLOBALS['FOObar'],
+ 99
+ );
+
+ $instance->reset();
+
+ $this->assertEquals(
+ $GLOBALS['FOObar'],
+ 42
+ );
+
+ unset( $GLOBALS['FOObar'] );
+ }
+
+ public function testTrySetGlobalForInvalidKey() {
+
+ $instance = new MaintenanceHelper();
+ $instance->setGlobalToValue( 'FOObar', 99 );
+
+ $this->assertFalse(
+ isset( $GLOBALS['FOObar'] )
+ );
+ }
+
+ /**
+ * @dataProvider runtimeKeyValueProvider
+ */
+ public function testRuntimeMonitor( $runtimeKey ) {
+
+ $instance = new MaintenanceHelper();
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getRuntimeValues()
+ );
+
+ $instance->initRuntimeValues();
+
+ $this->assertArrayHasKey(
+ $runtimeKey,
+ $instance->getRuntimeValues()
+ );
+
+ $instance->reset();
+ }
+
+ public function testTransformRuntimeValuesForOutput() {
+
+ $instance = new MaintenanceHelper();
+ $instance->initRuntimeValues();
+
+ $this->assertContains(
+ 'sec',
+ $instance->getFormattedRuntimeValues()
+ );
+
+ $instance->reset();
+ }
+
+ public function runtimeKeyValueProvider() {
+
+ $provider = [
+ [ 'time' ],
+ [ 'memory-before' ],
+ [ 'memory-after' ],
+ [ 'memory-used' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceLoggerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceLoggerTest.php
new file mode 100644
index 00000000..89c89c74
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/MaintenanceLoggerTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace SMW\Tests\Maintenance;
+
+use SMW\Maintenance\MaintenanceLogger;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Maintenance\MaintenanceLogger
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class MaintenanceLoggerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $manualEntryLogger = $this->getMockBuilder( '\SMW\MediaWiki\ManualEntryLogger' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Maintenance\MaintenanceLogger',
+ new MaintenanceLogger( 'Foo', $manualEntryLogger )
+ );
+ }
+
+ public function testLog() {
+
+ $manualEntryLogger = $this->getMockBuilder( '\SMW\MediaWiki\ManualEntryLogger' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $manualEntryLogger->expects( $this->once() )
+ ->method( 'log' )
+ ->with(
+ $this->stringContains( 'maintenance' ),
+ $this->equalTo( 'Foo' ),
+ $this->equalTo( 'Foo' ),
+ $this->stringContains( 'bar' ) );
+
+ $instance = new MaintenanceLogger( 'Foo', $manualEntryLogger );
+ $instance->log( 'bar' );
+ }
+
+ public function testLogWithInvalidNameLengthThrowsException() {
+
+ $manualEntryLogger = $this->getMockBuilder( '\SMW\MediaWiki\ManualEntryLogger' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $manualEntryLogger->expects( $this->never() )
+ ->method( 'log' );
+
+ $instance = new MaintenanceLogger( 'Foo', $manualEntryLogger );
+ $instance->setMaxNameChars( 2 );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->log( 'bar' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/PropertyStatisticsRebuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/PropertyStatisticsRebuilderTest.php
new file mode 100644
index 00000000..aa71051d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Maintenance/PropertyStatisticsRebuilderTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests\Maintenance;
+
+use FakeResultWrapper;
+use SMW\Maintenance\PropertyStatisticsRebuilder;
+
+/**
+ * @covers \SMW\Maintenance\PropertyStatisticsRebuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class PropertyStatisticsRebuilderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ PropertyStatisticsRebuilder::class,
+ new PropertyStatisticsRebuilder( $store, $propertyStatisticsStore )
+ );
+ }
+
+ public function testRebuildStatisticsStoreAndInsertCountRows() {
+
+ $tableName = 'Foobar';
+
+ $uRow = new \stdClass;
+ $uRow->count = 1111;
+
+ $nRow = new \stdClass;
+ $nRow->count = 1;
+
+ $res = [
+ 'smw_title' => 'Foo',
+ 'smw_id' => 9999
+ ];
+
+ $resultWrapper = new FakeResultWrapper(
+ [ (object)$res ]
+ );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->atLeastOnce() )
+ ->method( 'getTableFields' )
+ ->will( $this->returnValue( [] ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $database->expects( $this->atLeastOnce() )
+ ->method( 'selectRow' )
+ ->with(
+ $this->stringContains( $tableName ),
+ $this->anything(),
+ $this->equalTo( [ 'p_id' => 9999 ] ),
+ $this->anything() )
+ ->will( $this->onConsecutiveCalls( $uRow, $nRow ) );
+
+ $store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $this->newPropertyTable( $tableName ) ] ) );
+
+ $propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyStatisticsStore->expects( $this->atLeastOnce() )
+ ->method( 'insertUsageCount' )
+ ->with(
+ $this->equalTo( 9999 ),
+ $this->equalTo( [ 1110, 1 ] ) );
+
+ $instance = new PropertyStatisticsRebuilder(
+ $store,
+ $propertyStatisticsStore
+ );
+
+ $instance->rebuild();
+ }
+
+ protected function newPropertyTable( $propertyTableName, $fixedPropertyTable = false ) {
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isFixedPropertyTable', 'getName' ] )
+ ->getMock();
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( $fixedPropertyTable ) );
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( $propertyTableName ) );
+
+ return $propertyTable;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiQueryResultFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiQueryResultFormatterTest.php
new file mode 100644
index 00000000..53858fb2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiQueryResultFormatterTest.php
@@ -0,0 +1,344 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\MediaWiki\Api\ApiQueryResultFormatter;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\Api\ApiQueryResultFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ApiQueryResultFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Api\ApiQueryResultFormatter',
+ new ApiQueryResultFormatter( $queryResult )
+ );
+ }
+
+ public function testInvalidSetIndexedTagNameThrowsException() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ApiQueryResultFormatter( $queryResult );
+ $instance->setIsRawMode( true );
+
+ // Used to work in PHP 5 but not with PHP 7, made the
+ // method public to test the exception without reflection
+ // $reflector = new ReflectionClass( 'SMW\MediaWiki\Api\ApiQueryResultFormatter' );
+ // $method = $reflector->getMethod( 'setIndexedTagName' );
+ // $method->setAccessible( true );
+ // $method->invoke( $instance, $arr, null )
+
+ $arr = [];
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->setIndexedTagName( $arr, null );
+ }
+
+ /**
+ * @dataProvider resultDataProvider
+ */
+ public function testResultFormat( array $parameters, array $expected ) {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'toArray' )
+ ->will( $this->returnValue( $parameters['result'] ) );
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'hasFurtherResults' )
+ ->will( $this->returnValue( $parameters['furtherResults'] ) );
+
+ $instance = new ApiQueryResultFormatter( $queryResult );
+
+ $instance->setIsRawMode( $parameters['rawMode'] );
+ $instance->doFormat();
+
+ $this->assertEquals( 'query', $instance->getType() );
+
+ $this->assertEquals(
+ $expected['result'],
+ $instance->getResult()
+ );
+
+ $this->assertEquals(
+ $expected['continueOffset'],
+ $instance->getContinueOffset()
+ );
+ }
+
+ /**
+ * @dataProvider errorDataProvider
+ */
+ public function testErrorFormat( array $parameters, array $expected ) {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( $parameters['errors'] ) );
+
+ $instance = new ApiQueryResultFormatter( $queryResult );
+
+ $instance->setIsRawMode( $parameters['rawMode'] );
+ $instance->doFormat();
+
+ $this->assertEquals( 'error', $instance->getType() );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getResult()
+ );
+ }
+
+ public function resultDataProvider() {
+
+ $result = [
+ 'results' => [
+ 'Foo' => [
+ 'printouts' => [ 'lula' => [ 'lila' ] ]
+ ]
+ ],
+ 'printrequests' => [ 'Bar' ],
+ 'meta' => [ 'count' => 5, 'offset' => 5 ]
+ ];
+
+ $xml = [
+ 'results' => [
+ [
+ 'printouts' => [
+ [ 'label' => 'lula', 'lila', '_element' => 'value' ],
+ '_element' => 'property' ]
+ ],
+ '_element' => 'subject'
+ ],
+ 'printrequests' => [
+ 'Bar',
+ '_element' => 'printrequest'
+ ],
+ 'meta' => [ 'count' => 5, 'offset' => 5, '_element' => 'meta' ]
+ ];
+
+ $provider = [];
+
+ // #0 Without further results
+ $provider[] = [
+ [
+ 'result' => $result,
+ 'rawMode' => false,
+ 'furtherResults' => false
+ ],
+ [
+ 'result' => $result,
+ 'continueOffset' => false
+ ]
+ ];
+
+ // #1 Without further results + XML
+ $provider[] = [
+ [
+ 'result' => $result,
+ 'rawMode' => true,
+ 'furtherResults' => false
+ ],
+ [
+ 'result' => $xml,
+ 'continueOffset' => false
+ ]
+ ];
+
+ // #2 With further results
+ $provider[] = [
+ [
+ 'result' => $result,
+ 'rawMode' => false,
+ 'furtherResults' => true
+ ],
+ [
+ 'result' => $result,
+ 'continueOffset' => 10
+ ]
+ ];
+
+ // #3 With further results + XML
+ $provider[] = [
+ [
+ 'result' => $result,
+ 'rawMode' => true,
+ 'furtherResults' => true
+ ],
+ [
+ 'result' => $xml,
+ 'continueOffset' => 10
+ ]
+ ];
+
+
+ // #4 Extended subject data + XML
+ $provider[] = [
+ [
+ 'result' => [
+ 'results' => [
+ 'Foo' => [
+ 'printouts' => [
+ 'lula' => [ 'lila' ] ],
+ 'fulltext' => 'Foo' ]
+ ],
+ 'printrequests' => [ 'Bar' ],
+ 'meta' => [
+ 'count' => 5,
+ 'offset' => 5
+ ]
+ ],
+ 'rawMode' => true,
+ 'furtherResults' => true
+ ],
+ [
+ 'result' => [
+ 'results' => [
+ [
+ 'printouts' => [
+ [
+ 'label' => 'lula',
+ 'lila', '_element' => 'value'
+ ], '_element' => 'property' ],
+ 'fulltext' => 'Foo'
+ ], '_element' => 'subject'
+ ],
+ 'printrequests' => [ 'Bar', '_element' => 'printrequest' ],
+ 'meta' => [
+ 'count' => 5,
+ 'offset' => 5,
+ '_element' => 'meta'
+ ]
+ ],
+ 'continueOffset' => 10
+ ]
+ ];
+
+ // #5 printouts without values + XML
+ $provider[] = [
+ [
+ 'result' => [
+ 'results' => [
+ 'Foo' => [
+ 'printouts' => [ 'lula' ],
+ 'fulltext' => 'Foo' ]
+ ],
+ 'printrequests' => [ 'Bar' ],
+ 'meta' => [
+ 'count' => 5,
+ 'offset' => 5
+ ]
+ ],
+ 'rawMode' => true,
+ 'furtherResults' => true
+ ],
+ [
+ 'result' => [
+ 'results' => [
+ [
+ 'printouts' => [ '_element' => 'property' ],
+ 'fulltext' => 'Foo'
+ ],
+ '_element' => 'subject'
+ ],
+ 'printrequests' => [ 'Bar', '_element' => 'printrequest' ],
+ 'meta' => [
+ 'count' => 5,
+ 'offset' => 5,
+ '_element' => 'meta'
+ ]
+ ],
+ 'continueOffset' => 10
+ ]
+ ];
+
+ // #6 empty results + XML
+ $provider[] = [
+ [
+ 'result' => [
+ 'results' => [],
+ 'printrequests' => [ 'Bar' ],
+ 'meta' => [
+ 'count' => 0,
+ 'offset' => 0
+ ]
+ ],
+ 'rawMode' => true,
+ 'furtherResults' => false
+ ],
+ [
+ 'result' => [
+ 'results' => [],
+ 'printrequests' => [ 'Bar', '_element' => 'printrequest' ],
+ 'meta' => [
+ 'count' => 0,
+ 'offset' => 0,
+ '_element' => 'meta'
+ ]
+ ],
+ 'continueOffset' => 0
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function errorDataProvider() {
+
+ $errors = [ 'Foo', 'Bar' ];
+
+ $provider = [];
+
+ // #0
+ $provider[] = [
+ [
+ 'rawMode'=> false,
+ 'errors' => $errors
+ ],
+ [
+ 'query' => $errors
+ ]
+ ];
+
+ // #1
+ $provider[] = [
+ [
+ 'rawMode'=> true,
+ 'errors' => $errors
+ ],
+ [
+ 'query' => array_merge( $errors, [ '_element' => 'info' ] )
+ ]
+ ];
+
+ return $provider;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiRequestParameterFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiRequestParameterFormatterTest.php
new file mode 100644
index 00000000..7ab1fdd9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/ApiRequestParameterFormatterTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\MediaWiki\Api\ApiRequestParameterFormatter;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Api\ApiRequestParameterFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ApiRequestParameterFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ public function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ public function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Api\ApiRequestParameterFormatter',
+ new ApiRequestParameterFormatter( [] )
+ );
+ }
+
+ public function testGetAskArgsApiForEmptyParameter() {
+
+ $nstance = new ApiRequestParameterFormatter( [] );
+
+ $this->assertEmpty( $nstance->getAskArgsApiParameter( 'conditions' ) );
+ $this->assertEmpty( $nstance->getAskArgsApiParameter( 'parameters' ) );
+ $this->assertEmpty( $nstance->getAskArgsApiParameter( 'printouts' ) );
+ }
+
+ /**
+ * @dataProvider requestArgsApiParametersDataProvider
+ */
+ public function testGetAskArgsApiParameter( $parameters, $type, $expected ) {
+
+ $nstance = new ApiRequestParameterFormatter( $parameters );
+
+ $this->assertEquals(
+ $expected,
+ $nstance->getAskArgsApiParameter( $type )
+ );
+ }
+
+ /**
+ * @dataProvider requestAskApiParametersDataProvider
+ */
+ public function testGetAskApiParameters( $parameters, $expected ) {
+
+ $instance = new ApiRequestParameterFormatter( $parameters );
+ $result = $instance->getAskApiParameters();
+
+ $this->assertInternalType( 'array', $result );
+ $this->assertEquals( $expected, $result );
+ }
+
+ public function requestArgsApiParametersDataProvider() {
+ return [
+ [ [ 'conditions' => [ 'Lala' ] ], 'conditions', '[[Lala]]' ],
+ [ [ 'conditions' => [ 'Lala', 'Lima' ] ], 'conditions', '[[Lala]] [[Lima]]' ],
+ [ [ 'parameters' => [ 'Lila' ] ], 'parameters', [] ],
+ [ [ 'parameters' => [ 'Lila=isFunny' ] ], 'parameters', [ 'Lila' => 'isFunny' ] ],
+ [ [ 'parameters' => [ 'Lila=isFunny', 'Lula=isHappy' ] ], 'parameters', [ 'Lila' => 'isFunny', 'Lula' => 'isHappy' ] ],
+ // array( array( 'printouts' => array( '?Linda' ) ), 'printouts', array( $this->newPrintRequest( '?Linda' ) ) ),
+ // array( array( 'printouts' => array( '?Luna', '?Mars' ) ), 'printouts', array( $this->newPrintRequest( '?Luna' ), $this->newPrintRequest( '?Mars' ) ) ),
+ ];
+ }
+
+ public function requestAskApiParametersDataProvider() {
+ return [
+ [ [], [] ],
+ [ [ 'query' => '[[Modification date::+]]' ], [ '[[Modification date::+]]' ] ],
+ [ [ 'query' => '[[Modification date::+]]|?Modification date' ], [ '[[Modification date::+]]', '?Modification date' ] ],
+ [ [ 'query' => '[[Modification date::+]]|?Modification date|sort=desc' ], [ '[[Modification date::+]]', '?Modification date', 'sort=desc' ] ],
+ ];
+ }
+
+ private function newPrintRequest( $printout ) {
+ return new \SMW\Query\PrintRequest(
+ \SMW\Query\PrintRequest::PRINT_PROP,
+ $printout,
+ \SMW\DataValueFactory::getInstance()->newPropertyValueByLabel( $printout )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskArgsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskArgsTest.php
new file mode 100644
index 00000000..80a809ff
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskArgsTest.php
@@ -0,0 +1,269 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Api\AskArgs;
+use SMW\Tests\Utils\MwApiFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Api\AskArgs
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class AskArgsTest extends \PHPUnit_Framework_TestCase {
+
+ private $apiFactory;
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->apiFactory = new MwApiFactory();
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ ApplicationFactory::clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new AskArgs(
+ $this->apiFactory->newApiMain( [] ),
+ 'askargs'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Api\AskArgs',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testExecuteOnStore( array $query, array $expected ) {
+
+ $results = $this->apiFactory->doApiRequest( [
+ 'action' => 'askargs',
+ 'conditions' => $query['conditions'],
+ 'printouts' => $query['printouts'],
+ 'parameters' => $query['parameters'],
+ ] );
+
+ $this->assertInternalType( 'array', $results );
+
+ if ( isset( $expected['error'] ) ) {
+ return $this->assertArrayHasKey( 'error', $results );
+ }
+
+ $this->assertEquals(
+ $expected,
+ $results['query']['printrequests']
+ );
+ }
+
+ public function testExecuteOnMockStore() {
+
+ $requestParameters = [
+ 'conditions' => 'Foo::+',
+ 'printouts' => 'Bar',
+ 'parameters' => 'sort=asc'
+ ];
+
+ $expected = [
+ 'query-continue-offset' => 10,
+ 'query' => [
+ 'results' => [
+ 'Foo' => [
+ 'printouts' => [ 'lula' => [ 'lila' ] ]
+ ]
+ ],
+ 'printrequests' => [ 'Bar' ],
+ 'meta' => [ 'count' => 5, 'offset' => 5 ]
+ ]
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnCallback( [ $this, 'mockStoreQueryResultCallback' ] ) );
+
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $instance = new AskArgs(
+ $this->apiFactory->newApiMain( $requestParameters ),
+ 'askargs'
+ );
+
+ $instance->execute();
+
+ // MW 1.25
+ $result = method_exists( $instance->getResult(), 'getResultData' ) ? $instance->getResult()->getResultData() : $instance->getResultData();
+
+ // This came with 1.25, no idea what this suppose to be
+ unset( $result['_type'] );
+
+ $this->assertInternalType( 'array', $result );
+ $this->assertEquals( $expected, $result );
+ }
+
+ public function mockStoreQueryResultCallback( $query ) {
+
+ $result = '';
+
+ if ( $query->getQueryString() === '[[Foo::+]]' ) {
+ $result = [
+ 'results' => [
+ 'Foo' => [
+ 'printouts' => [ 'lula' => [ 'lila' ] ]
+ ]
+ ],
+ 'printrequests' => [ 'Bar' ],
+ 'meta' => [ 'count' => 5, 'offset' => 5 ]
+ ];
+ }
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'toArray' )
+ ->will( $this->returnValue( $result ) );
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'hasFurtherResults' )
+ ->will( $this->returnValue( true ) );
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ return $queryResult;
+ }
+
+ public function queryDataProvider() {
+ return [
+
+ // #0 Query producing an error result
+ [
+ [
+ 'conditions' => '[[Modification date::+]]',
+ 'printouts' => null,
+ 'parameters' => null
+ ],
+ [
+ 'error' => true
+ ]
+ ],
+
+ // #1 Query producing an error result
+ [
+ [
+ 'conditions' => '[[Modification date::+]]',
+ 'printouts' => null,
+ 'parameters' => 'limit=10'
+ ],
+ [
+ 'error' => true
+ ]
+ ],
+
+ // #2 Query producing an error result
+ [
+ [
+ 'conditions' => '[[Modification date::+]]',
+ 'printouts' => 'Modification date',
+ 'parameters' => 'limit=10'
+ ],
+ [
+ 'error' => true
+ ]
+ ],
+
+ // #3 Query producing a return result
+ [
+ [
+ 'conditions' => 'Modification date::+',
+ 'printouts' => null,
+ 'parameters' => null
+ ],
+ [
+ [
+ 'label'=> '',
+ 'typeid' => '_wpg',
+ 'mode' => 2,
+ 'format' => false,
+ 'key' => '',
+ 'redi' => ''
+ ]
+ ]
+ ],
+
+ // #4 Query producing a return result
+ [
+ [
+ 'conditions' => 'Modification date::+',
+ 'printouts' => 'Modification date',
+ 'parameters' => null
+ ],
+ [
+ [
+ 'label'=> '',
+ 'typeid' => '_wpg',
+ 'mode' => 2,
+ 'format' => false,
+ 'key' => '',
+ 'redi' => ''
+ ],
+ [
+ 'label'=> 'Modification date',
+ 'typeid' => '_dat',
+ 'mode' => 1,
+ 'format' => '',
+ 'key' => '_MDAT',
+ 'redi' => ''
+ ]
+ ]
+ ],
+
+ // #5 Query producing a return result
+ [
+ [
+ 'conditions' => 'Modification date::+',
+ 'printouts' => 'Modification date',
+ 'parameters' => 'limit=1'
+ ],
+ [
+ [
+ 'label'=> '',
+ 'typeid' => '_wpg',
+ 'mode' => 2,
+ 'format' => false,
+ 'key' => '',
+ 'redi' => ''
+ ],
+ [
+ 'label'=> 'Modification date',
+ 'typeid' => '_dat',
+ 'mode' => 1,
+ 'format' => '',
+ 'key' => '_MDAT',
+ 'redi' => ''
+ ]
+ ]
+ ],
+ ];
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskTest.php
new file mode 100644
index 00000000..05804efd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/AskTest.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\MediaWiki\Api\Ask;
+use SMW\Tests\Utils\MwApiFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Ask
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class AskTest extends \PHPUnit_Framework_TestCase {
+
+ private $apiFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->apiFactory = new MwApiFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new Ask(
+ $this->apiFactory->newApiMain( [ 'query' => 'Foo' ] ),
+ 'ask'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Api\Ask',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider sampleQueryProvider
+ */
+ public function testExecute( array $query, array $expected ) {
+
+ $results = $this->apiFactory->doApiRequest( [
+ 'action' => 'ask',
+ 'query' => implode( '|', $query )
+ ] );
+
+ $this->assertInternalType( 'array', $results );
+
+ // If their is no printrequests array we expect an error array
+ if ( isset( $results['query']['printrequests'] ) ) {
+ return $this->assertEquals( $expected, $results['query']['printrequests'] );
+ }
+
+ $this->assertArrayHasKey( 'error', $results );
+ }
+
+ public function sampleQueryProvider() {
+
+ // #0 Standard query
+ $provider[] = [
+ [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'limit=10'
+ ],
+ [
+ [
+ 'label'=> '',
+ 'typeid' => '_wpg',
+ 'mode' => 2,
+ 'format' => false,
+ 'key' => '',
+ 'redi' => ''
+ ],
+ [
+ 'label'=> 'Modification date',
+ 'typeid' => '_dat',
+ 'mode' => 1,
+ 'format' => '',
+ 'key' => '_MDAT',
+ 'redi' => ''
+ ]
+ ]
+ ];
+
+ $provider[] = [
+ [
+ '[[Modification date::+!]]',
+ 'limit=3'
+ ],
+ [
+ [
+ 'error'=> 'foo',
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleAugmentorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleAugmentorTest.php
new file mode 100644
index 00000000..7b15550b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleAugmentorTest.php
@@ -0,0 +1,154 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\MediaWiki\Api\Browse\ArticleAugmentor;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\ArticleAugmentor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ArticleAugmentorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ArticleAugmentor::class,
+ new ArticleAugmentor( $titleFactory )
+ );
+ }
+
+ public function testAugmentOnFullText() {
+
+ $res = [
+ 'query' => [
+ 'Foo#0' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'ns' => 0
+ ]
+ ],
+ 'query-continue-offset' => 0,
+ 'version' => 1,
+ 'meta' => [
+ 'type' => 'property',
+ 'limit' => 50,
+ 'count' => 1
+ ]
+ ];
+
+ $parameters = [
+ 'fullText' => true
+ ];
+
+ $expected = [
+ 'Foo#0' => [
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'ns' => 0,
+ 'fullText' => 'NS:FOO'
+ ]
+ ];
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getFullText' )
+ ->will( $this->returnValue( 'NS:FOO' ) );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $titleFactory->expects( $this->any() )
+ ->method( 'newFromID' )
+ ->with( $this->equalTo( 42 ) )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new ArticleAugmentor(
+ $titleFactory
+ );
+
+ $instance->augment( $res, $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+ public function testAugmentOnFullURL() {
+
+ $res = [
+ 'query' => [
+ 'Foo#0' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'ns' => 0
+ ]
+ ],
+ 'query-continue-offset' => 0,
+ 'version' => 1,
+ 'meta' => [
+ 'type' => 'property',
+ 'limit' => 50,
+ 'count' => 1
+ ]
+ ];
+
+ $parameters = [
+ 'fullURL' => true
+ ];
+
+ $expected = [
+ 'Foo#0' => [
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'ns' => 0,
+ 'fullURL' => 'http://example.org/FOO'
+ ]
+ ];
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getFullURL' )
+ ->will( $this->returnValue( 'http://example.org/FOO' ) );
+
+ $titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $titleFactory->expects( $this->any() )
+ ->method( 'newFromID' )
+ ->with( $this->equalTo( 42 ) )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new ArticleAugmentor(
+ $titleFactory
+ );
+
+ $instance->augment( $res, $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleLookupTest.php
new file mode 100644
index 00000000..244c919e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ArticleLookupTest.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\MediaWiki\Api\Browse\ArticleLookup;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\ArticleLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ArticleLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $articleAugmentor = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\ArticleAugmentor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ArticleLookup::class,
+ new ArticleLookup( $connection, $articleAugmentor )
+ );
+ }
+
+ /**
+ * @dataProvider articleSearchProvider
+ */
+ public function testLookup( $search, $row, $condition, $expected ) {
+
+ $articleAugmentor = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\ArticleAugmentor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->with(
+ $this->anyThing(),
+ $this->anyThing(),
+ $this->stringContains( $condition ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new ArticleLookup(
+ $connection,
+ $articleAugmentor
+ );
+
+ $parameters = [
+ 'search' => $search
+ ];
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+ public function articleSearchProvider() {
+
+ $row = new \stdClass;
+ $row->page_title = 'Foo';
+ $row->page_id = 42;
+ $row->page_namespace = 0;
+
+ $provider[] = [
+ 'Foo',
+ $row,
+ 'page_title LIKE %Foo% ESCAPE ` OR page_title LIKE %Foo% ESCAPE ` OR page_title LIKE %FOO% ESCAPE ` OR page_title LIKE %foo% ESCAPE `',
+ [
+ 'Foo#0' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'ns' => 0
+ ]
+ ]
+ ];
+
+ $row = new \stdClass;
+ $row->page_title = 'Foo';
+ $row->page_id = 42;
+ $row->page_namespace = 12;
+
+ $provider[] = [
+ 'Help:Fo o',
+ $row,
+ 'page_namespace=12 AND (page_title LIKE %Fo`_o% ESCAPE ` OR page_title LIKE %Fo`_o% ESCAPE ` OR page_title LIKE %FO`_O% ESCAPE ` OR page_title LIKE %fo`_o% ESCAPE `)',
+ [
+ 'Foo#12' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'ns' => 12
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/CachingLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/CachingLookupTest.php
new file mode 100644
index 00000000..b3d3d677
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/CachingLookupTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\MediaWiki\Api\Browse\CachingLookup;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\CachingLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CachingLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lookup = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\Lookup' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ CachingLookup::class,
+ new CachingLookup( $cache, $lookup )
+ );
+ }
+
+ public function testLookupWithoutCache() {
+
+ $cacheTTL = 42;
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'save' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( $cacheTTL ) );
+
+ $lookup = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\Lookup' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getVersion', 'lookup' ] )
+ ->getMockForAbstractClass();
+
+ $lookup->expects( $this->atLeastOnce() )
+ ->method( 'lookup' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new CachingLookup(
+ $cache,
+ $lookup
+ );
+
+ $instance->setCacheTTL( $cacheTTL );
+
+ $parameters = [];
+
+ $instance->lookup( $parameters );
+ }
+
+ public function testLookupWithCache() {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( [] ) );
+
+ $cache->expects( $this->never() )
+ ->method( 'save' );
+
+ $lookup = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\Lookup' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getVersion', 'lookup' ] )
+ ->getMockForAbstractClass();
+
+ $lookup->expects( $this->never() )
+ ->method( 'lookup' );
+
+ $instance = new CachingLookup(
+ $cache,
+ $lookup
+ );
+
+ $parameters = [];
+
+ $instance->lookup( $parameters );
+ }
+
+ public function testLookupWithCacheBeingDisabled() {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->never() )
+ ->method( 'fetch' );
+
+ $cache->expects( $this->never() )
+ ->method( 'save' );
+
+ $lookup = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\Lookup' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getVersion', 'lookup' ] )
+ ->getMockForAbstractClass();
+
+ $lookup->expects( $this->atLeastOnce() )
+ ->method( 'lookup' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new CachingLookup(
+ $cache,
+ $lookup
+ );
+
+ $instance->setCacheTTL( false );
+
+ $parameters = [];
+
+ $instance->lookup( $parameters );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListAugmentorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListAugmentorTest.php
new file mode 100644
index 00000000..b6d09716
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListAugmentorTest.php
@@ -0,0 +1,194 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\MediaWiki\Api\Browse\ListAugmentor;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\ListAugmentor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ListAugmentorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ListAugmentor::class,
+ new ListAugmentor( $store )
+ );
+ }
+
+ public function testAugmentOnDescription() {
+
+ $res = [
+ 'query' => [
+ 'Foo' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo'
+ ]
+ ],
+ 'query-continue-offset' => 0,
+ 'version' => 1,
+ 'meta' => [
+ 'type' => 'property',
+ 'limit' => 50,
+ 'count' => 1
+ ]
+ ];
+
+ $parameters = [
+ 'description' => true,
+ 'lang' => [ 'en', 'ja' ]
+ ];
+
+ $expected = [
+ 'Foo' => [
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'description' => [
+ 'en' => '',
+ 'ja' => ''
+ ]
+ ]
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ListAugmentor(
+ $store
+ );
+
+ $instance->augment( $res, $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+ public function testAugmentOnPrefLabel() {
+
+ $res = [
+ 'query' => [
+ 'Foo' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo'
+ ]
+ ],
+ 'query-continue-offset' => 0,
+ 'version' => 1,
+ 'meta' => [
+ 'type' => 'property',
+ 'limit' => 50,
+ 'count' => 1
+ ]
+ ];
+
+ $parameters = [
+ 'prefLabel' => true,
+ 'lang' => [ 'en', 'ja' ]
+ ];
+
+ $expected = [
+ 'Foo' => [
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'prefLabel' => [
+ 'en' => '',
+ 'ja' => ''
+ ]
+ ]
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ListAugmentor(
+ $store
+ );
+
+ $instance->augment( $res, $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+ public function testAugmentOnUsageCount() {
+
+ $res = [
+ 'query' => [
+ 'Foo' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo'
+ ]
+ ],
+ 'query-continue-offset' => 0,
+ 'version' => 1,
+ 'meta' => [
+ 'type' => 'property',
+ 'limit' => 50,
+ 'count' => 1
+ ]
+ ];
+
+ $parameters = [
+ 'usageCount' => true
+ ];
+
+ $expected = [
+ 'Foo' => [
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'usageCount' => 1111
+ ]
+ ];
+
+ $row = new \stdClass;
+ $row->usage_count = 1111;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( $row ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new ListAugmentor(
+ $store
+ );
+
+ $instance->augment( $res, $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListLookupTest.php
new file mode 100644
index 00000000..1b9432a9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/ListLookupTest.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\MediaWiki\Api\Browse\ListLookup;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\ListLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ListLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $listAugmentor = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\ListAugmentor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ListLookup::class,
+ new ListLookup( $store, $listAugmentor )
+ );
+ }
+
+ /**
+ * @dataProvider namespaceProvider
+ */
+ public function testLookup( $ns, $title, $expected ) {
+
+ $row = new \stdClass;
+ $row->smw_title = $title;
+ $row->smw_id = 42;
+
+ $listAugmentor = $this->getMockBuilder( '\SMW\MediaWiki\Api\Browse\ListAugmentor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSQLOptions' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new ListLookup(
+ $store,
+ $listAugmentor
+ );
+
+ $parameters = [
+ 'ns' => $ns,
+ 'search' => 'Foo',
+ 'sort' => true
+ ];
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+ public function namespaceProvider() {
+
+ $provider[] = [
+ SMW_NS_PROPERTY,
+ 'Foo',
+ [
+ 'Foo' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo'
+ ]
+ ]
+ ];
+
+ $provider[] = [
+ NS_CATEGORY,
+ 'Foo',
+ [
+ 'Foo' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo'
+ ]
+ ]
+ ];
+
+ $provider[] = [
+ SMW_NS_CONCEPT,
+ 'Foo',
+ [
+ 'Foo' => [
+ 'id' => 42,
+ 'label' => 'Foo',
+ 'key' => 'Foo'
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PSubjectLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PSubjectLookupTest.php
new file mode 100644
index 00000000..6d4ad0d4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PSubjectLookupTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\DIProperty;
+use SMW\MediaWiki\Api\Browse\PSubjectLookup;
+use SMW\DIWikiPage;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\PSubjectLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PSubjectLookupTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PSubjectLookup::class,
+ new PSubjectLookup( $this->store )
+ );
+ }
+
+ /**
+ * @dataProvider lookupProvider
+ */
+ public function testLookup( $subject, $parameters, $expected ) {
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [ $subject ] ) );
+
+ $instance = new PSubjectLookup(
+ $this->store
+ );
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ $expected
+ );
+ }
+
+ public function lookupProvider() {
+
+ yield [
+ new DIWikiPage( 'Foo bar', NS_MAIN ),
+ [
+ 'search' => 'Foo',
+ 'property' => 'Bar'
+ ],
+ [
+ 'Foo bar'
+ ]
+ ];
+
+ yield [
+ new DIWikiPage( 'Foo bar', NS_HELP ),
+ [
+ 'search' => 'Foo',
+ 'property' => 'Bar',
+ 'title-prefix' => false
+ ],
+ [
+ 'Foo bar'
+ ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PValueLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PValueLookupTest.php
new file mode 100644
index 00000000..c071c467
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/PValueLookupTest.php
@@ -0,0 +1,281 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\DIProperty;
+use SMW\MediaWiki\Api\Browse\PValueLookup;
+use SMW\MediaWiki\Connection\Query;
+use SMW\Services\ServicesContainer;
+use FakeResultWrapper;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\PValueLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PValueLookupTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'service' )
+ ->with( $this->equalTo( 'ProximityPropertyValueLookup' ) )
+ ->will( $this->returnValue( new \SMW\SQLStore\Lookup\ProximityPropertyValueLookup( $this->store ) ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PValueLookup::class,
+ new PValueLookup( $this->store )
+ );
+ }
+
+ public function testLookup_wpg_property() {
+
+ $row = new \stdClass;
+ $row->smw_title = 'Test';
+ $row->smw_id = 42;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = new Query( $connection );
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( new FakeResultWrapper( [ $row ] ) ) );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID', 'isFixedPropertyTable' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $idTable->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new PValueLookup(
+ $this->store
+ );
+
+ $parameters = [
+ 'search' => 'Foo',
+ 'property' => 'Bar'
+ ];
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ [
+ 'Test'
+ ]
+ );
+
+ $this->assertContains(
+ '[{"OR":"smw_sortkey LIKE %Foo%"},{"OR":"smw_sortkey LIKE %Foo%"},{"OR":"smw_sortkey LIKE %FOO%"}]',
+ $query->__toString()
+ );
+ }
+
+ public function testLookup_wpg_propertyChain() {
+
+ $row = new \stdClass;
+ $row->smw_title = 'Test';
+ $row->smw_id = 42;
+
+ $query = $this->getMockBuilder( '\SMW\MediaWiki\Connection\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( new FakeResultWrapper( [ $row ] ) ) );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID', 'isFixedPropertyTable' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->with( $this->equalTo( new DIProperty( 'Foobar' ) ) )
+ ->will( $this->returnValue( 42 ) );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new PValueLookup(
+ $this->store
+ );
+
+ $parameters = [
+ 'search' => 'Foo',
+ 'property' => 'Bar.Foobar'
+ ];
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ [
+ 'Test'
+ ]
+ );
+ }
+
+ public function testLookup_txt_property() {
+
+ $row = new \stdClass;
+ $row->o_hash = 'Test';
+ $row->smw_id = 42;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = new Query( $connection );
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( new FakeResultWrapper( [ $row ] ) ) );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID', 'isFixedPropertyTable' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $idTable->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->any() )
+ ->method( 'getLabelField' )
+ ->will( $this->returnValue( 'o_hash' ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new PValueLookup(
+ $this->store
+ );
+
+ $parameters = [
+ 'search' => 'Foo',
+ 'property' => 'Text'
+ ];
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertEquals(
+ $res['query'],
+ [
+ 'Test'
+ ]
+ );
+
+ $this->assertContains(
+ '[{"OR":"o_hash LIKE %Foo%"},{"OR":"o_hash LIKE %Foo%"},{"OR":"o_hash LIKE %FOO%"},{"AND":"p_id=42"}]',
+ $query->__toString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/SubjectLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/SubjectLookupTest.php
new file mode 100644
index 00000000..85082f33
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/Browse/SubjectLookupTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api\Browse;
+
+use SMW\DIProperty;
+use SMW\MediaWiki\Api\Browse\SubjectLookup;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\SubjectLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SubjectLookupTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SubjectLookup::class,
+ new SubjectLookup( $this->store )
+ );
+ }
+
+ public function testLookup_HTML() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $instance = new SubjectLookup(
+ $this->store
+ );
+
+ $parameters = [
+ 'subject' => 'Foo',
+ 'ns' => NS_MAIN,
+ 'options' => [],
+ 'type' => 'html'
+ ];
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertArrayHasKey(
+ 'query',
+ $res
+ );
+
+ $this->assertArrayHasKey(
+ 'meta',
+ $res
+ );
+ }
+
+ public function testLookup_JSON() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $instance = new SubjectLookup(
+ $this->store
+ );
+
+ $parameters = [
+ 'subject' => 'Foo',
+ 'ns' => NS_MAIN
+ ];
+
+ $res = $instance->lookup( $parameters );
+
+ $this->assertArrayHasKey(
+ 'query',
+ $res
+ );
+
+ $this->assertArrayHasKey(
+ 'meta',
+ $res
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseByPropertyTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseByPropertyTest.php
new file mode 100644
index 00000000..12623cec
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseByPropertyTest.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\MediaWiki\Api\BrowseByProperty;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Api\BrowseByProperty
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class BrowseByPropertyTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $apiFactory;
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->applicationFactory->registerObject( 'Store', $this->store );
+
+ $this->apiFactory = UtilityFactory::getInstance()->newMwApiFactory();
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new BrowseByProperty(
+ $this->apiFactory->newApiMain( [] ),
+ 'browsebyproperty'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Api\BrowseByProperty',
+ $instance
+ );
+ }
+
+ public function testExecute() {
+
+ $list[] = [
+ new DIProperty( 'Foo' ),
+ 42
+ ];
+
+ $list[] = [
+ new DIProperty( 'Foaf:Foo' ),
+ 1001
+ ];
+
+ $list[] = [
+ new DIProperty( 'Unknown:Foo' ),
+ 1001
+ ];
+
+ $cachedListLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\CachedListLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cachedListLookup->expects( $this->once() )
+ ->method( 'fetchList' )
+ ->will( $this->returnValue( $list ) );
+
+ $this->store->expects( $this->once() )
+ ->method( 'getPropertiesSpecial' )
+ ->will( $this->returnValue( $cachedListLookup ) );
+
+ $this->applicationFactory->registerObject( 'Store', $this->store );
+
+ $result = $this->apiFactory->doApiRequest( [
+ 'action' => 'browsebyproperty',
+ 'property' => 'Foo'
+ ] );
+
+ $this->assertArrayHasKey(
+ 'query',
+ $result
+ );
+
+ $this->assertArrayHasKey(
+ 'version',
+ $result
+ );
+
+ $this->assertArrayHasKey(
+ 'query-continue-offset',
+ $result
+ );
+
+ $this->assertArrayHasKey(
+ 'meta',
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseBySubjectTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseBySubjectTest.php
new file mode 100644
index 00000000..01c0da31
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseBySubjectTest.php
@@ -0,0 +1,238 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Api\BrowseBySubject;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Api\BrowseBySubject
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class BrowseBySubjectTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $apiFactory;
+ private $semanticDataFactory;
+
+ private $applicationFactory;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $utilityFactory = $this->testEnvironment->getUtilityFactory();
+
+ $this->apiFactory = $utilityFactory->newMwApiFactory();
+ $this->semanticDataFactory = $utilityFactory->newSemanticDataFactory();
+ $this->stringValidator = $utilityFactory->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new BrowseBySubject(
+ $this->apiFactory->newApiMain( ['subject' => 'Foo' ] ),
+ 'browsebysubject'
+ );
+
+ $this->assertInstanceOf(
+ BrowseBySubject::class,
+ $instance
+ );
+ }
+
+ public function testExecuteForValidSubject() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $expectedResultToContainArrayKeys = [
+ 'error' => false,
+ 'result' => true
+ ];
+
+ $result = $this->apiFactory->doApiRequest( [
+ 'action' => 'browsebysubject',
+ 'subject' => 'Foo'
+ ] );
+
+ $this->assertToContainArrayKeys(
+ $expectedResultToContainArrayKeys,
+ $result
+ );
+ }
+
+ public function testExecuteForInvalidSubjectThrowsException() {
+ $this->setExpectedException( interface_exists( 'Throwable' ) ? 'Throwable' : 'Exception' );
+
+ $result = $this->apiFactory->doApiRequest( [
+ 'action' => 'browsebysubject',
+ 'subject' => '{}'
+ ] );
+ }
+
+ public function testRawJsonPrintOutput() {
+
+ $parameters = [ 'subject' => 'Foo', 'subobject' => 'Bar' ];
+
+ $dataItem = new DIWikiPage(
+ 'Foo',
+ NS_MAIN,
+ '',
+ 'Bar'
+ );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( $dataItem );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSemanticData' )
+ ->with( $this->equalTo( $dataItem ) )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new BrowseBySubject(
+ $this->apiFactory->newApiMain( $parameters ),
+ 'browsebysubject'
+ );
+
+ // Went away with 1.26/1.27
+ if ( function_exists( 'setRawMode' ) ) {
+ $instance->getMain()->getResult()->setRawMode();
+ }
+
+ $instance->execute();
+
+ $printer = $instance->getMain()->createPrinterByName( 'json' );
+
+ ob_start();
+ $printer->initPrinter( false );
+ $printer->execute();
+ $printer->closePrinter();
+ $out = ob_get_clean();
+
+ $this->stringValidator->assertThatStringContains(
+ '"subject":"Foo#0##Bar"',
+ $out
+ );
+ }
+
+
+ public function testHtmlJsonPrintOutput() {
+
+ $parameters = [
+ 'subject' => 'Foo',
+ 'subobject' => 'Bar',
+ 'type' => 'html'
+ ];
+
+ $dataItem = new DIWikiPage(
+ 'Foo',
+ NS_MAIN,
+ '',
+ 'Bar'
+ );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( $dataItem );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSemanticData' )
+ ->with( $this->equalTo( $dataItem ) )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new BrowseBySubject(
+ $this->apiFactory->newApiMain( $parameters ),
+ 'browsebysubject'
+ );
+
+ // Went away with 1.26/1.27
+ if ( function_exists( 'setRawMode' ) ) {
+ $instance->getMain()->getResult()->setRawMode();
+ }
+
+ $instance->execute();
+
+ $printer = $instance->getMain()->createPrinterByName( 'json' );
+
+ ob_start();
+ $printer->initPrinter( false );
+ $printer->execute();
+ $printer->closePrinter();
+ $out = ob_get_clean();
+
+ $this->stringValidator->assertThatStringContains(
+ '"query":"<div class=\"smwb-datasheet.*\"><div class=\"smw-table smwb-factbox\">',
+ $out
+ );
+ }
+
+ public function assertToContainArrayKeys( $setup, $result ) {
+ $this->assertInternalArrayStructure(
+ $setup, $result, 'error', 'array', function( $r ) { return $r['error'];
+ } );
+
+ $this->assertInternalArrayStructure(
+ $setup, $result, 'result', 'array', function( $r ) { return $r['query'];
+ } );
+
+ $this->assertInternalArrayStructure(
+ $setup, $result, 'subject', 'string', function( $r ) { return $r['query']['subject'];
+ } );
+
+ $this->assertInternalArrayStructure(
+ $setup, $result, 'data', 'array', function( $r ) { return $r['query']['data'];
+ } );
+
+ $this->assertInternalArrayStructure(
+ $setup, $result, 'sobj', 'array', function( $r ) { return $r['query']['sobj'];
+ } );
+ }
+
+ protected function assertInternalArrayStructure( $setup, $result, $field, $internalType, $definition ) {
+
+ if ( isset( $setup[$field] ) && $setup[$field] ) {
+
+ $this->assertInternalType(
+ $internalType,
+ is_callable( $definition ) ? $definition( $result ) : $definition
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseTest.php
new file mode 100644
index 00000000..2ce2ba21
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/BrowseTest.php
@@ -0,0 +1,230 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\MediaWiki\Api\Browse;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class BrowseTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $apiFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment(
+ [
+ 'smwgCacheUsage' => [ 'api.browse' => true ]
+ ]
+ );
+
+ $this->apiFactory = $this->testEnvironment->getUtilityFactory()->newMwApiFactory();
+
+ $proximityPropertyValueLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\ProximityPropertyValueLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'service' )
+ ->with( $this->equalTo( 'ProximityPropertyValueLookup' ) )
+ ->will( $this->returnValue( $proximityPropertyValueLookup ) );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new Browse(
+ $this->apiFactory->newApiMain( [] ),
+ 'smwbrowse'
+ );
+
+ $this->assertInstanceOf(
+ Browse::class,
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider browseIdProvider
+ */
+ public function testExecute( $id, $parameters = [] ) {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( false ) );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $resultWrapper = $this->getMockBuilder( '\FakeResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMW\MediaWiki\Connection\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'query' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSQLOptions' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+
+ $instance = new Browse(
+ $this->apiFactory->newApiMain(
+ [
+ 'action' => 'smwbrowse',
+ 'browse' => $id,
+ 'params' => json_encode( [ 'search' => 'Foo' ] + $parameters )
+ ]
+ ),
+ 'smwbrowse'
+ );
+
+ $instance->execute();
+ }
+
+ public function testExecute_Subject() {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubSemanticData' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+
+ $instance = new Browse(
+ $this->apiFactory->newApiMain(
+ [
+ 'action' => 'smwbrowse',
+ 'browse' => 'subject',
+ 'params' => json_encode( [ 'subject' => 'Bar', 'ns' => 0 ] )
+ ]
+ ),
+ 'smwbrowse'
+ );
+
+ $instance->execute();
+ }
+
+ public function browseIdProvider() {
+
+ $provider[] = [
+ 'property'
+ ];
+
+ $provider[] = [
+ 'category'
+ ];
+
+ $provider[] = [
+ 'concept'
+ ];
+
+ $provider[] = [
+ 'page'
+ ];
+
+ $provider[] = [
+ 'pvalue',
+ [ 'property' => 'Bar' ]
+ ];
+
+ $provider[] = [
+ 'psubject',
+ [ 'property' => 'Bar' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/InfoTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/InfoTest.php
new file mode 100644
index 00000000..22105713
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/InfoTest.php
@@ -0,0 +1,180 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\MediaWiki\Api\Info;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Info
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class InfoTest extends \PHPUnit_Framework_TestCase {
+
+ private $apiFactory;
+ private $jobQueue;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->apiFactory = $this->testEnvironment->getUtilityFactory()->newMwApiFactory();
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $this->jobQueue );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new Info(
+ $this->apiFactory->newApiMain( [] ),
+ 'smwinfo'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Api\Info',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider typeDataProvider
+ */
+ public function testExecuteOnStore( $queryParameters, $expectedType ) {
+
+ $result = $this->apiFactory->doApiRequest( [
+ 'action' => 'smwinfo',
+ 'info' => $queryParameters
+ ] );
+
+ if ( $expectedType === 'integer' ) {
+ return $this->assertGreaterThanOrEqual( 0, $result['info'][$queryParameters] );
+ }
+
+ $this->assertInternalType(
+ 'array',
+ $result['info'][$queryParameters]
+ );
+ }
+
+ /**
+ * @dataProvider countDataProvider
+ */
+ public function testExecuteOnMockStore( $statistics, $type, $expected ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getStatistics' )
+ ->will( $this->returnValue( $statistics ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new Info(
+ $this->apiFactory->newApiMain( [ 'info' => $type ] ),
+ 'smwinfo'
+ );
+
+ $instance->execute();
+
+ // MW 1.25
+ $result = method_exists( $instance->getResult(), 'getResultData' ) ? $instance->getResult()->getResultData() : $instance->getResultData();
+
+ // This came with 1.25, no idea what this suppose to be
+ unset( $result['_type'] );
+
+ $this->assertEquals(
+ $expected,
+ $result['info'][$type]
+ );
+ }
+
+ /**
+ * Test unknown query parameter
+ *
+ * Only valid parameters will yield an info array while an unknown parameter
+ * will produce a "warnings" array.
+ *
+ * @since 1.9
+ */
+ public function testUnknownQueryParameter() {
+
+ $data = $this->apiFactory->doApiRequest( [
+ 'action' => 'smwinfo',
+ 'info' => 'Foo'
+ ] );
+
+ $this->assertInternalType(
+ 'array',
+ $data['warnings']
+ );
+ }
+
+ public function testJobCount() {
+
+ $this->jobQueue->expects( $this->any() )
+ ->method( 'getQueueSize' )
+ ->will( $this->returnValue( 1 ) );
+
+ $result = $this->apiFactory->doApiRequest(
+ [
+ 'action' => 'smwinfo',
+ 'info' => 'jobcount'
+ ]
+ );
+
+ $this->assertArrayHasKey(
+ 'smw.update',
+ $result['info']['jobcount']
+ );
+ }
+
+ public function countDataProvider() {
+ return [
+ [ [ 'QUERYFORMATS' => [ 'table' => 3 ] ], 'formatcount', [ 'table' => 3 ] ],
+ [ [ 'PROPUSES' => 34 ], 'propcount', 34 ],
+ [ [ 'ERRORUSES' => 42 ], 'errorcount', 42 ],
+ [ [ 'USEDPROPS' => 51 ], 'usedpropcount', 51 ],
+ [ [ 'TOTALPROPS' => 52 ], 'totalpropcount', 52 ],
+ [ [ 'DECLPROPS' => 67 ], 'declaredpropcount', 67 ],
+ [ [ 'OWNPAGE' => 99 ], 'proppagecount', 99 ],
+ [ [ 'QUERY' => 11 ], 'querycount', 11 ],
+ [ [ 'QUERYSIZE' => 24 ], 'querysize', 24 ],
+ [ [ 'CONCEPTS' => 17 ], 'conceptcount', 17 ],
+ [ [ 'SUBOBJECTS' => 88 ], 'subobjectcount', 88 ],
+ ];
+ }
+
+ public function typeDataProvider() {
+ return [
+ [ 'proppagecount', 'integer' ],
+ [ 'propcount', 'integer' ],
+ [ 'errorcount', 'integer' ],
+ [ 'querycount', 'integer' ],
+ [ 'usedpropcount', 'integer' ],
+ [ 'totalpropcount', 'integer' ],
+ [ 'declaredpropcount', 'integer' ],
+ [ 'conceptcount', 'integer' ],
+ [ 'querysize', 'integer' ],
+ [ 'subobjectcount', 'integer' ],
+ [ 'formatcount', 'array' ],
+ [ 'jobcount', 'array' ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/PropertyListByApiRequestTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/PropertyListByApiRequestTest.php
new file mode 100644
index 00000000..86126390
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/PropertyListByApiRequestTest.php
@@ -0,0 +1,146 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\DIProperty;
+use SMW\MediaWiki\Api\PropertyListByApiRequest;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Api\PropertyListByApiRequest
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class PropertyListByApiRequestTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Api\PropertyListByApiRequest',
+ new PropertyListByApiRequest( $this->store, $propertySpecificationLookup )
+ );
+ }
+
+ public function testGetSerializedListForProperty() {
+
+ $list[] = [
+ new DIProperty( 'Foo' ),
+ 42
+ ];
+
+ $list[] = [
+ new DIProperty( 'Foaf:Foo' ),
+ 1001
+ ];
+
+ $list[] = [
+ new \SMWDIError( 'error' ),
+ -1
+ ];
+
+ $list[] = [];
+
+ $isCached = true;
+
+ $expectedSerializedPropertyList = [
+ 'Foo' => [
+ 'label' => 'Foo',
+ 'key' => 'Foo',
+ 'isUserDefined' => true,
+ 'usageCount' => 42,
+ 'description' => ''
+ ],
+ 'Foaf:Foo' => [
+ 'label' => 'Foaf:Foo',
+ 'key' => 'Foaf:Foo',
+ 'isUserDefined' => true,
+ 'usageCount' => 1001,
+ 'description' => ''
+ ]
+ ];
+
+ $expectedNamespaces = [
+ 'Foaf'
+ ];
+
+ $expectedMeta = [
+ 'limit' => 3,
+ 'count' => 2,
+ 'isCached' => $isCached
+ ];
+
+ $cachedListLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\CachedListLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cachedListLookup->expects( $this->once() )
+ ->method( 'fetchList' )
+ ->will( $this->returnValue( $list ) );
+
+ $cachedListLookup->expects( $this->once() )
+ ->method( 'isFromCache' )
+ ->will( $this->returnValue( $isCached ) );
+
+ $this->store->expects( $this->once() )
+ ->method( 'getPropertiesSpecial' )
+ ->will( $this->returnValue( $cachedListLookup ) );
+
+ $propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyListByApiRequest( $this->store, $propertySpecificationLookup );
+ $instance->setLimit( 3 );
+
+ $this->assertTrue(
+ $instance->findPropertyListBy( 'Foo' )
+ );
+
+ $this->assertEquals(
+ $expectedSerializedPropertyList,
+ $instance->getPropertyList()
+ );
+
+ $this->assertEquals(
+ $expectedNamespaces,
+ $instance->getNamespaces()
+ );
+
+ $this->assertEquals(
+ $expectedMeta,
+ $instance->getMeta()
+ );
+
+ $this->assertEquals(
+ 3,
+ $instance->getContinueOffset()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/QueryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/QueryTest.php
new file mode 100644
index 00000000..bdbdb17c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/QueryTest.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use ReflectionClass;
+use SMW\ApplicationFactory;
+use SMW\Tests\Utils\MwApiFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Query
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class QueryTest extends \PHPUnit_Framework_TestCase {
+
+ private $apiFactory;
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->apiFactory = new MwApiFactory();
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ ApplicationFactory::clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\Api\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Api\Query',
+ $instance
+ );
+ }
+
+ public function testQueryAndQueryResult() {
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\Api\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reflector = new ReflectionClass( '\SMW\MediaWiki\Api\Query' );
+ $getQuery = $reflector->getMethod( 'getQuery' );
+ $getQuery->setAccessible( true );
+ $query = $getQuery->invoke( $instance, '[[Modification date::+]]', [], [] );
+
+ $this->assertInstanceOf(
+ '\SMWQuery',
+ $query
+ );
+
+ $getQueryResult = $reflector->getMethod( 'getQueryResult' );
+ $getQueryResult->setAccessible( true );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $getQueryResult->invoke( $instance, $query )
+ );
+ }
+
+ public function testAddQueryResultOnMockStore() {
+
+ // Minimalistic test case to verify executability
+ // For a full coverage, use Api\QueryResultFormatterTest
+ $test = [
+ 'results' => [
+ 'Foo' => [
+ 'printouts' => [ 'lula' => [ 'lila' ] ]
+ ]
+ ],
+ 'printrequests' => [ 'Bar' ],
+ 'meta' => [ 'count' => 5, 'offset' => 5 ]
+ ];
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'toArray' )
+ ->will( $this->returnValue( $test ) );
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'hasFurtherResults' )
+ ->will( $this->returnValue( true ) );
+
+ $apiResult = $this->apiFactory->newApiResult( [] );
+
+ $reflector = new ReflectionClass( '\SMW\MediaWiki\Api\Query' );
+ $method = $reflector->getMethod( 'addQueryResult' );
+ $method->setAccessible( true );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\Api\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance->expects( $this->atLeastOnce() )
+ ->method( 'getResult' )
+ ->will( $this->returnValue( $apiResult ) );
+
+ $method->invoke( $instance, $queryResult );
+
+ // MW 1.25
+ $result = method_exists( $apiResult, 'getResultData' ) ? $apiResult->getResultData() : $instance->getData();
+
+ // This came with 1.25, no idea what this suppose to be
+ unset( $result['warnings'] );
+ unset( $result['_type'] );
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ //$this->assertEquals(
+ // array( 'query' => $test, 'query-continue-offset' => 10 ),
+ // $result
+ //);
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/TaskTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/TaskTest.php
new file mode 100644
index 00000000..c99aaf19
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Api/TaskTest.php
@@ -0,0 +1,252 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Api;
+
+use SMW\MediaWiki\Api\Task;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Task
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TaskTest extends \PHPUnit_Framework_TestCase {
+
+ private $apiFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->apiFactory = $this->testEnvironment->getUtilityFactory()->newMwApiFactory();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new Task(
+ $this->apiFactory->newApiMain( [] ),
+ 'smwtask'
+ );
+
+ $this->assertInstanceOf(
+ Task::class,
+ $instance
+ );
+ }
+
+ public function testUpdateTask() {
+
+ $updateJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\UpdateJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $updateJob->expects( $this->atLeastOnce() )
+ ->method( 'run' );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->atLeastOnce() )
+ ->method( 'newUpdateJob' )
+ ->will( $this->returnValue( $updateJob ) );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $instance = new Task(
+ $this->apiFactory->newApiMain( [
+ 'action' => 'smwtask',
+ 'task' => 'update',
+ 'params' => json_encode( [ 'subject' => 'Foo#0##', 'ref' => [ 'Bar' ] ] ),
+ 'token' => 'foo'
+ ]
+ ),
+ 'smwtask'
+ );
+
+ $instance->execute();
+ }
+
+ public function testDupLookupTask() {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $cache->expects( $this->once() )
+ ->method( 'save' );
+
+ $entityTable = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityTable->expects( $this->atLeastOnce() )
+ ->method( 'findDuplicates' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $entityTable ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+
+ $instance = new Task(
+ $this->apiFactory->newApiMain(
+ [
+ 'action' => 'smwtask',
+ 'task' => 'duplookup',
+ 'params' => [],
+ 'token' => 'foo'
+ ]
+ ),
+ 'smwtask'
+ );
+
+ $instance->execute();
+ }
+
+ public function testGenericJobTask() {
+
+ $nullJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\NullJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $nullJob->expects( $this->atLeastOnce() )
+ ->method( 'insert' );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->atLeastOnce() )
+ ->method( 'newByType' )
+ ->with(
+ $this->equalTo( 'Foobar' ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( $nullJob ) );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $instance = new Task(
+ $this->apiFactory->newApiMain(
+ [
+ 'action' => 'smwtask',
+ 'task' => 'job',
+ 'params' => json_encode(
+ [
+ 'subject' => 'Foo#0##',
+ 'job' => 'Foobar'
+ ]
+ ),
+ 'token' => 'foo'
+ ]
+ ),
+ 'smwtask'
+ );
+
+ $instance->execute();
+ }
+
+ public function testRunJobListTask() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueue->expects( $this->atLeastOnce() )
+ ->method( 'runFromQueue' )
+ ->with( $this->equalTo( [ 'FooJob' => 1 ] ) )
+ ->will( $this->returnValue( '--job-done' ) );
+
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+
+ $instance = new Task(
+ $this->apiFactory->newApiMain(
+ [
+ 'action' => 'smwtask',
+ 'task' => 'run-joblist',
+ 'params' => json_encode(
+ [
+ 'subject' => 'Foo#0##',
+ 'jobs' => [ 'FooJob' => 1 ]
+ ]
+ ),
+ 'token' => 'foo'
+ ]
+ ),
+ 'smwtask'
+ );
+
+ $instance->execute();
+ }
+
+ public function testCheckQueryTask() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new Task(
+ $this->apiFactory->newApiMain(
+ [
+ 'action' => 'smwtask',
+ 'task' => 'check-query',
+ 'params' => json_encode(
+ [
+ 'subject' => 'Foo#0##',
+ 'query' => [
+ 'query_hash_1#result_hash_2' => [
+ 'parameters' => [
+ 'limit' => 5,
+ 'offset' => 0,
+ 'querymode' => 1
+ ],
+ 'conditions' => ''
+ ]
+ ]
+ ]
+ ),
+ 'token' => 'foo'
+ ]
+ ),
+ 'smwtask'
+ );
+
+ $instance->execute();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/CollatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/CollatorTest.php
new file mode 100644
index 00000000..ae26e4c3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/CollatorTest.php
@@ -0,0 +1,190 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\Collator;
+
+/**
+ * @covers \SMW\MediaWiki\Collator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CollatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Collator::class,
+ Collator::singleton()
+ );
+ }
+
+ public function testIsIdentical() {
+
+ $collation = $this->getMockBuilder( '\Collation' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $collation->expects( $this->exactly( 2 ) )
+ ->method( 'getSortKey' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new Collator(
+ $collation
+ );
+
+ $this->assertTrue(
+ $instance->isIdentical( 'Foo', 'Foo' )
+ );
+ }
+
+ /**
+ * @dataProvider uppercaseProvider
+ */
+ public function testGetFirstLetterOnUppercaseCollation( $text, $firstLetter, $sortKey ) {
+
+ $instance = Collator::singleton( 'uppercase' );
+
+ $this->assertSame(
+ $firstLetter,
+ $instance->getFirstLetter( $text )
+ );
+
+ $this->assertSame(
+ $sortKey,
+ $instance->getSortKey( $text )
+ );
+ }
+
+ /**
+ * @dataProvider identityProvider
+ */
+ public function testGetFirstLetterOnIdentityCollation( $text, $firstLetter, $sortKey ) {
+
+ $instance = Collator::singleton( 'identity' );
+
+ $this->assertSame(
+ $firstLetter,
+ $instance->getFirstLetter( $text )
+ );
+
+ $this->assertSame(
+ $sortKey,
+ $instance->getSortKey( $text )
+ );
+ }
+
+ /**
+ * @dataProvider armorProvider
+ */
+ public function testArmor( $collation, $text, $expected ) {
+
+ $instance = Collator::singleton( $collation );
+
+ $this->assertSame(
+ $expected,
+ $instance->armor( $instance->getSortKey( $text ) )
+ );
+ }
+
+ public function testArmorOnUCA() {
+
+ if ( !extension_loaded( 'intl' ) ) {
+ $this->markTestSkipped( 'Skipping because intl (ICU) is not availabe.' );
+ }
+
+ $instance = Collator::singleton( 'uca-default' );
+ $text = 'XmlTest';
+
+ $this->assertNotSame(
+ $text,
+ $instance->armor( $instance->getSortKey( $text ) )
+ );
+ }
+
+ public function uppercaseProvider() {
+
+ $provider[] = [
+ '',
+ '',
+ ''
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'F',
+ 'FOO'
+ ];
+
+ $provider[] = [
+ 'foo',
+ 'F',
+ 'FOO'
+ ];
+
+ $provider[] = [
+ 'テスト',
+ 'テ',
+ 'テスト'
+ ];
+
+ $provider[] = [
+ '\0テスト',
+ '\\',
+ '\0テスト'
+ ];
+
+ return $provider;
+ }
+
+ public function identityProvider() {
+
+ $provider[] = [
+ '',
+ '',
+ ''
+ ];
+
+ $provider[] = [
+ 'Foo',
+ 'F',
+ 'Foo'
+ ];
+
+ $provider[] = [
+ 'foo',
+ 'f',
+ 'foo'
+ ];
+
+ $provider[] = [
+ 'テスト',
+ 'テ',
+ 'テスト'
+ ];
+
+ $provider[] = [
+ '\0テスト',
+ '\\',
+ '\0テスト'
+ ];
+
+ return $provider;
+ }
+
+ public function armorProvider() {
+
+ $provider[] = [
+ 'uppercase',
+ 'XmlTest',
+ 'XMLTEST'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/ConnectionProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/ConnectionProviderTest.php
new file mode 100644
index 00000000..6f1fa938
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/ConnectionProviderTest.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Connection;
+
+use SMW\MediaWiki\Connection\ConnectionProvider;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\Connection\ConnectionProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ConnectionProviderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+ $this->assertInstanceOf(
+ ConnectionProvider::class,
+ new ConnectionProvider()
+ );
+ }
+
+ public function testGetConnection() {
+
+ $instance = new ConnectionProvider();
+ $instance->setLogger(
+ TestEnvironment::newSpyLogger()
+ );
+
+ $connection = $instance->getConnection();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Database',
+ $connection
+ );
+
+ $this->assertSame(
+ $connection,
+ $instance->getConnection()
+ );
+
+ $instance->releaseConnection();
+
+ $this->assertNotSame(
+ $connection,
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetConnectionOnFixedConfWithSameIndex() {
+
+ $instance = new ConnectionProvider(
+ 'foo'
+ );
+
+ $instance->setLogger(
+ TestEnvironment::newSpyLogger()
+ );
+
+ $conf = [
+ 'foo' => [
+ 'read' => 'Bar',
+ 'write' => 'Bar'
+ ]
+ ];
+
+ $instance->setLocalConnectionConf( $conf );
+
+ $connection = $instance->getConnection();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Database',
+ $connection
+ );
+
+ $this->assertSame(
+ $connection,
+ $instance->getConnection()
+ );
+
+ $instance->releaseConnection();
+
+ $this->assertNotSame(
+ $connection,
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetConnectionOnCallback() {
+
+ $db = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ConnectionProvider(
+ 'foo'
+ );
+
+ $conf = [
+ 'foo' => [
+ 'callback' => function() use( $db ) {
+ return $db;
+ }
+ ]
+ ];
+
+ $instance->setLocalConnectionConf( $conf );
+
+ $connection = $instance->getConnection();
+
+ $this->assertSame(
+ $db,
+ $instance->getConnection()
+ );
+
+ $instance->releaseConnection();
+ }
+
+ public function testGetConnectionOnIncompleteConfThrowsException() {
+
+ $instance = new ConnectionProvider(
+ 'foo'
+ );
+
+ $conf = [
+ 'foo' => [
+ 'read' => 'Foo'
+ ]
+ ];
+
+ $instance->setLocalConnectionConf( $conf );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getConnection();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/DatabaseTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/DatabaseTest.php
new file mode 100644
index 00000000..58afbadb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/DatabaseTest.php
@@ -0,0 +1,609 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Connection;
+
+use SMW\Connection\ConnectionProviderRef;
+use SMW\Tests\PHPUnitCompat;
+use SMW\MediaWiki\Connection\Database;
+
+/**
+ * @covers \SMW\MediaWiki\Connection\Database
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DatabaseTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connectionProviderRef;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->connectionProviderRef = $this->getMockBuilder( '\SMW\Connection\ConnectionProviderRef' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Database::class,
+ new Database( $this->connectionProviderRef )
+ );
+ }
+
+ public function testNewQuery() {
+
+ $instance = new Database(
+ $this->connectionProviderRef
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Connection\Query',
+ $instance->newQuery()
+ );
+ }
+
+ public function testNumRowsMethod() {
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'numRows' ] )
+ ->getMockForAbstractClass();
+
+ $database->expects( $this->once() )
+ ->method( 'numRows' )
+ ->with( $this->equalTo( 'Fuyu' ) )
+ ->will( $this->returnValue( 1 ) );
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $connectionProvider
+ ]
+ )
+ );
+
+ $this->assertEquals(
+ 1,
+ $instance->numRows( 'Fuyu' )
+ );
+ }
+
+ public function testAddQuotesMethod() {
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'addQuotes' ] )
+ ->getMockForAbstractClass();
+
+ $database->expects( $this->once() )
+ ->method( 'addQuotes' )
+ ->with( $this->equalTo( 'Fan' ) )
+ ->will( $this->returnValue( 'Fan' ) );
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $connectionProvider
+ ]
+ )
+ );
+
+ $this->assertEquals(
+ 'Fan',
+ $instance->addQuotes( 'Fan' )
+ );
+ }
+
+ /**
+ * @dataProvider dbTypeProvider
+ */
+ public function testTableNameMethod( $type ) {
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableName', 'getType' ] )
+ ->getMockForAbstractClass();
+
+ $database->expects( $this->any() )
+ ->method( 'tableName' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $database->expects( $this->once() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( $type ) );
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $connectionProvider
+ ]
+ )
+ );
+
+ $instance->setDBPrefix( 'bar_' );
+
+ $expected = $type === 'sqlite' ? 'bar_Foo' : 'Foo';
+
+ $this->assertEquals(
+ $expected,
+ $instance->tableName( 'Foo' )
+ );
+ }
+
+ public function testSelectMethod() {
+
+ $resultWrapper = $this->getMockBuilder( 'ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'select' ] )
+ ->getMockForAbstractClass();
+
+ $database->expects( $this->once() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $connectionProvider
+ ]
+ )
+ );
+
+ $this->assertInstanceOf(
+ 'ResultWrapper',
+ $instance->select( 'Foo', 'Bar', '', __METHOD__ )
+ );
+ }
+
+ public function testSelectFieldMethod() {
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'selectField' ] )
+ ->getMockForAbstractClass();
+
+ $database->expects( $this->once() )
+ ->method( 'selectField' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $connectionProvider
+ ]
+ )
+ );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->selectField( 'Foo', 'Bar', '', __METHOD__, [] )
+ );
+ }
+
+ /**
+ * @dataProvider querySqliteProvider
+ */
+ public function testQueryOnSQLite( $query, $expected ) {
+
+ $resultWrapper = $this->getMockBuilder( 'ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $read = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getType' ] )
+ ->getMockForAbstractClass();
+
+ $read->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'sqlite' ) );
+
+ $readConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $readConnectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $read ) );
+
+ $write = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'query' ] )
+ ->getMockForAbstractClass();
+
+ $write->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->equalTo( $expected ) )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $writeConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $writeConnectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $write ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $readConnectionProvider,
+ 'write' => $writeConnectionProvider
+ ]
+ )
+ );
+
+ $this->assertInstanceOf(
+ 'ResultWrapper',
+ $instance->query( $query )
+ );
+ }
+
+ public function querySqliteProvider() {
+
+ $provider = [
+ [ 'TEMPORARY', 'TEMP' ],
+ [ 'RAND', 'RANDOM' ],
+ [ 'ENGINE=MEMORY', '' ],
+ [ 'DROP TEMP', 'DROP' ]
+ ];
+
+ return $provider;
+ }
+
+ public function testSelectThrowsException() {
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'select' ] )
+ ->getMockForAbstractClass();
+
+ $database->expects( $this->once() )
+ ->method( 'select' );
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $connectionProvider
+ ]
+ )
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ $this->assertInstanceOf(
+ 'ResultWrapper',
+ $instance->select( 'Foo', 'Bar', '', __METHOD__ )
+ );
+ }
+
+ public function testQueryThrowsException() {
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'query' ] )
+ ->getMockForAbstractClass();
+
+ $databaseException = new \DBError( $database, 'foo' );
+
+ $database->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->throwException( $databaseException ) );
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionProvider->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $connectionProvider,
+ 'write' => $connectionProvider
+ ]
+ )
+ );
+
+ $this->setExpectedException( 'Exception' );
+ $instance->query( 'Foo', __METHOD__ );
+ }
+
+ public function testGetEmptyTransactionTicket() {
+
+ $readConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $writeConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $loadBalancerFactory = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getEmptyTransactionTicket', 'hasMasterChanges' ] )
+ ->getMock();
+
+ $loadBalancerFactory->expects( $this->once() )
+ ->method( 'hasMasterChanges' )
+ ->will( $this->returnValue( false ) );
+
+ $loadBalancerFactory->expects( $this->once() )
+ ->method( 'getEmptyTransactionTicket' );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $readConnectionProvider,
+ 'write' => $writeConnectionProvider
+ ]
+ ),
+ $loadBalancerFactory
+ );
+
+ $instance->getEmptyTransactionTicket( __METHOD__ );
+ }
+
+ public function testGetEmptyTransactionTicketOnMasterChanges() {
+
+ $readConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $writeConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $loadBalancerFactory = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getEmptyTransactionTicket', 'hasMasterChanges' ] )
+ ->getMock();
+
+ $loadBalancerFactory->expects( $this->once() )
+ ->method( 'hasMasterChanges' )
+ ->will( $this->returnValue( true ) );
+
+ $loadBalancerFactory->expects( $this->never() )
+ ->method( 'getEmptyTransactionTicket' );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $readConnectionProvider,
+ 'write' => $writeConnectionProvider
+ ]
+ ),
+ $loadBalancerFactory
+ );
+
+ $this->assertNull(
+ $instance->getEmptyTransactionTicket( __METHOD__ )
+ );
+ }
+
+ public function testCommitAndWaitForReplication() {
+
+ $readConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $writeConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $loadBalancerFactory = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'commitAndWaitForReplication' ] )
+ ->getMock();
+
+ $loadBalancerFactory->expects( $this->once() )
+ ->method( 'commitAndWaitForReplication' );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $readConnectionProvider,
+ 'write' => $writeConnectionProvider
+ ]
+ ),
+ $loadBalancerFactory
+ );
+
+ $instance->commitAndWaitForReplication( __METHOD__, 123 );
+ }
+
+ public function testDoQueryWithAutoCommit() {
+
+ $database = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getFlag', 'clearFlag', 'setFlag', 'getType', 'query' ] )
+ ->getMockForAbstractClass();
+
+ $database->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $database->expects( $this->any() )
+ ->method( 'getFlag' )
+ ->will( $this->returnValue( true ) );
+
+ $database->expects( $this->once() )
+ ->method( 'clearFlag' );
+
+ $database->expects( $this->once() )
+ ->method( 'setFlag' );
+
+ $readConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $readConnectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $writeConnectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $writeConnectionProvider->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $instance = new Database(
+ new ConnectionProviderRef(
+ [
+ 'read' => $readConnectionProvider,
+ 'write' => $writeConnectionProvider
+ ]
+ )
+ );
+
+ $instance->setFlag( Database::AUTO_COMMIT );
+ $instance->query( 'foo', __METHOD__, false );
+ }
+
+ /**
+ * @dataProvider missingWriteConnectionProvider
+ */
+ public function testMissingWriteConnectionThrowsException( $func, $args ) {
+
+ $connectionProvider = $this->getMockBuilder( '\SMW\Connection\ConnectionProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Database(
+ new ConnectionProviderRef( [] )
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ call_user_func_array( [ $instance, $func ], $args );
+ }
+
+ public function dbTypeProvider() {
+ return [
+ [ 'mysql' ],
+ [ 'sqlite' ],
+ [ 'postgres' ]
+ ];
+ }
+
+ public function missingWriteConnectionProvider() {
+
+ yield [
+ 'query', [ 'foo' ]
+ ];
+
+ yield [
+ 'nextSequenceValue', [ 'foo' ]
+ ];
+
+ yield [
+ 'insertId', []
+ ];
+
+ yield [
+ 'clearFlag', [ 'Foo' ]
+ ];
+
+ yield [
+ 'getFlag', [ 'Foo' ]
+ ];
+
+ yield [
+ 'setFlag', [ 'Foo' ]
+ ];
+
+ yield [
+ 'insert', [ 'Foo', 'Bar' ]
+ ];
+
+ yield [
+ 'update', [ 'Foo', 'Bar', 'Foobar' ]
+ ];
+
+ yield [
+ 'delete', [ 'Foo', 'Bar' ]
+ ];
+
+ yield [
+ 'replace', [ 'Foo', 'Bar', 'Foobar' ]
+ ];
+
+ yield [
+ 'makeList', [ 'Foo', 'Bar' ]
+ ];
+
+ yield [
+ 'beginAtomicTransaction', [ 'Foo' ]
+ ];
+
+ yield [
+ 'endAtomicTransaction', [ 'Foo' ]
+ ];
+
+ yield [
+ 'onTransactionIdle', [ 'Foo' ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/LoadBalancerConnectionProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/LoadBalancerConnectionProviderTest.php
new file mode 100644
index 00000000..71568ed7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/LoadBalancerConnectionProviderTest.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Connection;
+
+use DatabaseBase;
+use ReflectionClass;
+use SMW\Tests\PHPUnitCompat;
+use SMW\MediaWiki\Connection\LoadBalancerConnectionProvider;
+
+/**
+ * @covers \SMW\MediaWiki\Connection\LoadBalancerConnectionProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class LoadBalancerConnectionProviderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ LoadBalancerConnectionProvider::class,
+ new LoadBalancerConnectionProvider( DB_SLAVE )
+ );
+ }
+
+ public function testGetAndReleaseConnection() {
+
+ $instance = new LoadBalancerConnectionProvider(
+ DB_SLAVE
+ );
+
+ $connection = $instance->getConnection();
+
+ $this->assertInstanceOf(
+ 'DatabaseBase',
+ $instance->getConnection()
+ );
+
+ $this->assertTrue(
+ $instance->getConnection() === $connection
+ );
+
+ $instance->releaseConnection();
+ }
+
+ public function testGetConnectionThrowsException() {
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ $instance = new LoadBalancerConnectionProvider(
+ DB_SLAVE
+ );
+
+ $reflector = new ReflectionClass(
+ LoadBalancerConnectionProvider::class
+ );
+
+ $connection = $reflector->getProperty( 'connection' );
+ $connection->setAccessible( true );
+ $connection->setValue( $instance, 'invalid' );
+
+ $this->assertInstanceOf(
+ 'DatabaseBase',
+ $instance->getConnection()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/OptionsBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/OptionsBuilderTest.php
new file mode 100644
index 00000000..1567fb0d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/OptionsBuilderTest.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Connection;
+
+use SMW\MediaWiki\Connection\OptionsBuilder;
+
+/**
+ * @covers \SMW\MediaWiki\Connection\OptionsBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class OptionsBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+ $this->assertInstanceOf(
+ OptionsBuilder::class,
+ new OptionsBuilder()
+ );
+ }
+
+ /**
+ * @dataProvider optionsProvider
+ */
+ public function testMakeSelectOptions( $options ) {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'array',
+ OptionsBuilder::makeSelectOptions( $connection, $options )
+ );
+ }
+
+ /**
+ * @dataProvider optionsProvider
+ */
+ public function testToString( $options ) {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'string',
+ OptionsBuilder::toString( $options )
+ );
+ }
+
+ public function optionsProvider() {
+
+ $provider[] = [
+ [ 'FOR UPDATE' ]
+ ];
+
+ $provider[] = [
+ [ 'GROUP BY' => [ 'Foo', 'Bar' ] ]
+ ];
+
+ $provider[] = [
+ [ 'ORDER BY' => [ 'Foo', 'Bar' ] ]
+ ];
+
+ $provider[] = [
+ [
+ 'GROUP BY' => [ 'Foo', 'Bar' ],
+ 'ORDER BY' => [ 'Foo', 'Bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/QueryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/QueryTest.php
new file mode 100644
index 00000000..09e4fe68
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/QueryTest.php
@@ -0,0 +1,321 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Connection;
+
+use SMW\MediaWiki\Connection\Query;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\Connection\Query
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class QueryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connection;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableName' )
+ ->will( $this->returnArgument(0) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Query::class,
+ new Query( $this->connection )
+ );
+ }
+
+ public function testNoType_ThrowsException() {
+
+ $instance = new Query( $this->connection );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->build();
+ }
+
+ public function testNoFields_ThrowsException() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->build();
+ }
+
+ public function testNoJoinType_ThrowsException() {
+
+ $instance = new Query( $this->connection );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->join( 'foo' );
+ }
+
+ public function testTable_Field() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+ $instance->field( 'bar' );
+
+ $this->assertSame(
+ 'SELECT bar FROM foo',
+ $instance->build()
+ );
+ }
+
+ public function testTable_AS() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo', 't1' );
+ $instance->field( 'bar' );
+
+ $this->assertSame(
+ 'SELECT bar FROM foo AS t1',
+ $instance->build()
+ );
+ }
+
+ public function testTable_Field_Condition() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+ $instance->field( 'bar', 'b_ar' );
+ $instance->condition( 'foobar' );
+
+ $this->assertSame(
+ '{"tables":"foo","fields":[["bar","b_ar"]],"conditions":[["foobar"]],"joins":[],"options":[],"alias":"","index":0,"autocommit":false}',
+ (string)$instance
+ );
+
+ $this->assertSame(
+ 'SELECT bar AS b_ar FROM foo WHERE (foobar)',
+ $instance->build()
+ );
+ }
+
+ public function testField_HasField() {
+
+ $instance = new Query( $this->connection );
+ $instance->field( 'bar', 'b_ar' );
+
+ $this->assertTrue(
+ $instance->hasField()
+ );
+
+ $this->assertTrue(
+ $instance->hasField( 'bar' )
+ );
+
+ $this->assertFalse(
+ $instance->hasField( 'foo' )
+ );
+ }
+
+ public function testTable_Field_Conditions() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+
+ $instance->field( 'bar', 'b_ar' );
+ $instance->field( 'f', 'a' );
+
+ $instance->condition( 'foobar' );
+ $instance->condition( $instance->asAnd( 'foo_bar' ) );
+ $instance->condition( $instance->asOr( '_bar' ) );
+
+ $this->assertSame(
+ 'SELECT bar AS b_ar, f AS a FROM foo WHERE ((foobar) AND (foo_bar) OR (_bar))',
+ $instance->build()
+ );
+ }
+
+ public function testTable_Join_Field_Conditions() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+ $instance->join( 'INNER JOIN', 'abc as v1' );
+ $instance->join( 'LEFT JOIN', [ 'def' => 'v2' ] );
+
+ $instance->field( 'bar', 'b_ar' );
+ $instance->field( 'f', 'a' );
+
+ $instance->condition( 'foobar' );
+ $instance->condition( $instance->asAnd( 'foo_bar' ) );
+ $instance->condition( $instance->asOr( '_bar' ) );
+ $instance->condition( $instance->asOr( '_foo' ) );
+
+ $this->assertSame(
+ 'SELECT bar AS b_ar, f AS a FROM foo INNER JOIN abc as v1 LEFT JOIN def AS v2 WHERE (((foobar) AND (foo_bar) OR (_bar)) OR (_foo))',
+ $instance->build()
+ );
+ }
+
+ public function testTable_Join_ON_Field_Conditions() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+ $instance->field( 'f', 'a' );
+ $instance->join( 'LEFT JOIN', [ 'abc' => 'ON p=d' ] );
+
+ $instance->condition( $instance->asAnd( 'foo_bar' ) );
+
+ $this->assertSame(
+ 'SELECT f AS a FROM foo LEFT JOIN abc ON p=d WHERE (foo_bar)',
+ $instance->build()
+ );
+ }
+
+ public function testTable_Field_Condition_Options_Distinct_Order() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+ $instance->field( 'f', 'a' );
+
+ $instance->condition( $instance->asOr( 'foo_bar' ) );
+
+ $instance->options(
+ [
+ 'DISTINCT' => true,
+ 'ORDER BY' => '_foo',
+ 'LIMIT' => 42
+ ]
+ );
+
+ $this->assertSame(
+ 'SELECT DISTINCT f AS a FROM foo WHERE (foo_bar) ORDER BY _foo LIMIT 42',
+ $instance->build()
+ );
+ }
+
+ public function testTable_Field_Condition_Options_Group_Having() {
+
+ $instance = new Query( $this->connection );
+ $instance->type( 'select' );
+
+ $instance->table( 'foo' );
+ $instance->field( 'f', 'a' );
+
+ $instance->condition( $instance->asOr( 'foo_bar' ) );
+
+ $instance->options(
+ [
+ 'HAVING' => 'COUNT(Foo) > 5',
+ 'GROUP BY' => '_foo',
+ 'LIMIT' => 42
+ ]
+ );
+
+ $this->assertSame(
+ 'SELECT f AS a FROM foo WHERE (foo_bar) GROUP BY _foo HAVING COUNT(Foo) > 5 LIMIT 42',
+ $instance->build()
+ );
+
+ }
+
+ public function testTable() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableName' )
+ ->with( $this->equalTo( 'Bar' ) );
+
+ $instance = new Query(
+ $this->connection
+ );
+
+ $instance->table( 'Bar' );
+ }
+
+ public function testJoin() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableName' )
+ ->with( $this->equalTo( 'Foo' ) );
+
+ $instance = new Query(
+ $this->connection
+ );
+
+ $instance->join( 'INNER JOIN', [ 'Foo' => 'bar ...' ] );
+ }
+
+ public function testEq() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'addQuotes' )
+ ->with( $this->equalTo( 'Bar' ) )
+ ->will( $this->returnValue( '`Bar`' ) );
+
+ $instance = new Query(
+ $this->connection
+ );
+
+ $this->assertSame(
+ 'Foo=`Bar`',
+ $instance->eq( 'Foo', 'Bar' )
+ );
+ }
+
+ public function testNeq() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'addQuotes' )
+ ->with( $this->equalTo( 'Bar' ) )
+ ->will( $this->returnValue( '`Bar`' ) );
+
+ $instance = new Query(
+ $this->connection
+ );
+
+ $this->assertSame(
+ 'Foo!=`Bar`',
+ $instance->neq( 'Foo', 'Bar' )
+ );
+ }
+
+ public function testExecute() {
+
+ $instance = new Query(
+ $this->connection
+ );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with(
+ $this->equalTo( $instance ),
+ $this->equalTo( 'Foo' ) );
+
+
+ $instance->execute( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/SequenceTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/SequenceTest.php
new file mode 100644
index 00000000..3ec0ab44
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/SequenceTest.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Connection;
+
+use SMW\MediaWiki\Connection\Sequence;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\Connection\Sequence
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SequenceTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connection;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+ $this->assertInstanceOf(
+ Sequence::class,
+ new Sequence( $this->connection )
+ );
+ }
+
+ public function testConstructWithInvalidConnectionThrowsException() {
+ $this->setExpectedException( '\RuntimeException' );
+ new Sequence( 'Foo' );
+ }
+
+ public function testMakeSequence() {
+ $this->assertEquals(
+ 'Foo_bar_seq',
+ Sequence::makeSequence( 'Foo', 'bar' )
+ );
+ }
+
+ public function testNonPostgres() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'foo' ) );
+
+ $instance = new Sequence(
+ $this->connection
+ );
+
+ $this->assertEquals(
+ null,
+ $instance->restart( 'Foo', 'bar')
+ );
+ }
+
+ public function testPostgres() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'postgres' ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) { return $callback(); } ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->equalTo( 'ALTER SEQUENCE Foo_bar_seq RESTART WITH 43' ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'selectField' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new Sequence(
+ $this->connection
+ );
+
+ $this->assertEquals(
+ 43,
+ $instance->restart( 'Foo', 'bar' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/TransactionProfilerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/TransactionProfilerTest.php
new file mode 100644
index 00000000..72b070db
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Connection/TransactionProfilerTest.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Connection;
+
+use SMW\MediaWiki\Connection\TransactionProfiler;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\Connection\TransactionProfiler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TransactionProfilerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connection;
+
+ protected function setUp() {
+
+ $this->transactionProfiler = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'setSilenced' ] )
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+ $this->assertInstanceOf(
+ TransactionProfiler::class,
+ new TransactionProfiler( $this->transactionProfiler )
+ );
+ }
+
+ public function testSetSilenced_Enabled() {
+
+ $instance = new TransactionProfiler(
+ $this->transactionProfiler
+ );
+
+ $instance->silenceTransactionProfiler();
+
+ $this->transactionProfiler->expects( $this->once() )
+ ->method( 'setSilenced' );
+
+ $instance->setSilenced( true );
+ }
+
+ public function testSetSilenced_NotEnabled() {
+
+ $instance = new TransactionProfiler(
+ $this->transactionProfiler
+ );
+
+ $this->transactionProfiler->expects( $this->never() )
+ ->method( 'setSilenced' );
+
+ $instance->setSilenced( true );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/DeepRedirectTargetResolverTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/DeepRedirectTargetResolverTest.php
new file mode 100644
index 00000000..49604e38
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/DeepRedirectTargetResolverTest.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\DeepRedirectTargetResolver;
+use SMW\Tests\Utils\Mock\MockTitle;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\DeepRedirectTargetResolver
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class DeepRedirectTargetResolverTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\DeepRedirectTargetResolver',
+ new DeepRedirectTargetResolver( $pageCreator )
+ );
+ }
+
+ public function testResolveRedirectTarget() {
+
+ $title = MockTitle::buildMock( 'Uuuuuuuuuu' );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnValue( MockTitle::buildMock( 'Ooooooo' ) ) );
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $this->any() )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $wikiPage ) );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\DeepRedirectTargetResolver' )
+ ->setConstructorArgs( [ $pageCreator ] )
+ ->setMethods( [ 'isValidRedirectTarget', 'isRedirect' ] )
+ ->getMock();
+
+ $instance->expects( $this->atLeastOnce() )
+ ->method( 'isValidRedirectTarget' )
+ ->will( $this->returnValue( true ) );
+
+ $instance->expects( $this->at( 0 ) )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( true ) );
+
+ $this->assertInstanceOf(
+ '\Title',
+ $instance->findRedirectTargetFor( $title )
+ );
+ }
+
+ public function testResolveRedirectTargetThrowsException() {
+
+ $title = MockTitle::buildMock( 'Uuuuuuuuuu' );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->never() )
+ ->method( 'getRedirectTarget' );
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $this->any() )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $wikiPage ) );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\DeepRedirectTargetResolver' )
+ ->setConstructorArgs( [ $pageCreator ] )
+ ->setMethods( [ 'isValidRedirectTarget', 'isRedirect' ] )
+ ->getMock();
+
+ $instance->expects( $this->atLeastOnce() )
+ ->method( 'isValidRedirectTarget' )
+ ->will( $this->returnValue( false ) );
+
+ $instance->expects( $this->at( 0 ) )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( false ) );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->findRedirectTargetFor( $title );
+ }
+
+ public function testTryToResolveCircularRedirectThrowsException() {
+
+ $title = MockTitle::buildMock( 'Uuuuuuuuuu' );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnValue( $title ) );
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $this->any() )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $wikiPage ) );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\DeepRedirectTargetResolver' )
+ ->setConstructorArgs( [ $pageCreator ] )
+ ->setMethods( [ 'isRedirect' ] )
+ ->getMock();
+
+ $instance->expects( $this->any() )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( true ) );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->findRedirectTargetFor( $title );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/CallableUpdateTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/CallableUpdateTest.php
new file mode 100644
index 00000000..540045b6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/CallableUpdateTest.php
@@ -0,0 +1,237 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Deferred;
+
+use SMW\MediaWiki\Deferred\CallableUpdate;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Deferred\CallableUpdate
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class CallableUpdateTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $spyLogger;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyLogger = $this->testEnvironment->getUtilityFactory()->newSpyLogger();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->clearPendingDeferredUpdates();
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $callback = function() {
+ return null;
+ };
+
+ $this->assertInstanceOf(
+ CallableUpdate::class,
+ new CallableUpdate( $callback )
+ );
+ }
+
+ public function testUpdate() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new CallableUpdate(
+ $callback
+ );
+
+ $instance->setLogger( $this->spyLogger );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testUpdateOnEmptyCallback() {
+
+ $instance = new CallableUpdate();
+
+ $instance->setLogger( $this->spyLogger );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->assertContains(
+ 'Empty callback',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testUpdateOnLateCallback() {
+
+ $instance = new CallableUpdate();
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance->setCallback( $callback );
+
+ $instance->setLogger( $this->spyLogger );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->assertContains(
+ 'Added',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testWaitableUpdate() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new CallableUpdate(
+ $callback
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->markAsPending( true );
+ $instance->pushUpdate();
+
+ $instance->releasePendingUpdates();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testUpdateWithDisabledDeferredUpdate() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new CallableUpdate(
+ $callback
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->enabledDeferredUpdate( false );
+ $instance->pushUpdate();
+ }
+
+ public function testOrigin() {
+
+ $callback = function() {
+ };
+
+ $instance = new CallableUpdate(
+ $callback
+ );
+
+ $instance->setOrigin( 'Foo' );
+
+ $this->assertContains(
+ 'Foo',
+ $instance->getOrigin()
+ );
+ }
+
+ public function testFilterDuplicateQueueEntryByFingerprint() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new CallableUpdate(
+ $callback
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->setFingerprint( __METHOD__ );
+ $instance->markAsPending( true );
+ $instance->pushUpdate();
+
+ $instance = new CallableUpdate(
+ $callback
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->setFingerprint( __METHOD__ );
+ $instance->markAsPending( true );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testStage() {
+
+ $instance = new CallableUpdate();
+
+ $this->assertEquals(
+ 'post',
+ $instance->getStage()
+ );
+
+ $instance->asPresend();
+
+ $this->assertEquals(
+ 'pre',
+ $instance->getStage()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/ChangeTitleUpdateTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/ChangeTitleUpdateTest.php
new file mode 100644
index 00000000..a3e67e64
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/ChangeTitleUpdateTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Deferred;
+
+use SMW\MediaWiki\Deferred\ChangeTitleUpdate;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Deferred\ChangeTitleUpdate
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangeTitleUpdateTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $jobFactory;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'newUpdateJob' ] )
+ ->getMock();
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobFactory', $this->jobFactory );
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->clearPendingDeferredUpdates();
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ChangeTitleUpdate::class,
+ new ChangeTitleUpdate()
+ );
+ }
+
+ public function testDoUpdate() {
+
+ $nullJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\NullJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->atLeastOnce() )
+ ->method( 'newUpdateJob' )
+ ->will( $this->returnValue( $nullJob ) );
+
+ $oldTitle = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $newTitle = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ChangeTitleUpdate(
+ $oldTitle,
+ $newTitle
+ );
+
+ $instance->doUpdate();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/TransactionalCallableUpdateTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/TransactionalCallableUpdateTest.php
new file mode 100644
index 00000000..4505ba62
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Deferred/TransactionalCallableUpdateTest.php
@@ -0,0 +1,395 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Deferred;
+
+use SMW\MediaWiki\Deferred\TransactionalCallableUpdate;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Deferred\TransactionalCallableUpdate
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TransactionalCallableUpdateTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $spyLogger;
+ private $connection;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyLogger = $this->testEnvironment->getUtilityFactory()->newSpyLogger();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->clearPendingDeferredUpdates();
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $callback = function() {
+ return null;
+ };
+
+ $this->assertInstanceOf(
+ TransactionalCallableUpdate::class,
+ new TransactionalCallableUpdate( $callback, $this->connection )
+ );
+ }
+
+ public function testUpdate() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $this->connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testUpdateOnEmptyCallback() {
+
+ $instance = new TransactionalCallableUpdate(
+ null,
+ $this->connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->assertContains(
+ 'Empty callback',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testUpdateOnLateCallback() {
+
+ $instance = new TransactionalCallableUpdate(
+ null,
+ $this->connection
+ );
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance->setCallback( $callback );
+
+ $instance->setLogger( $this->spyLogger );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ $this->assertContains(
+ 'Added',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testWaitableUpdate() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $this->connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->markAsPending( true );
+ $instance->pushUpdate();
+
+ $instance->releasePendingUpdates();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testUpdateWithDisabledDeferredUpdate() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $this->connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->enabledDeferredUpdate( false );
+ $instance->pushUpdate();
+ }
+
+ public function testOrigin() {
+
+ $callback = function() {
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $this->connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->setOrigin( 'Foo' );
+
+ $this->assertContains(
+ 'Foo',
+ $instance->getOrigin()
+ );
+ }
+
+ public function testFilterDuplicateQueueEntryByFingerprint() {
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $this->connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->setFingerprint( __METHOD__ );
+ $instance->markAsPending( true );
+ $instance->pushUpdate();
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $this->connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->setFingerprint( __METHOD__ );
+ $instance->markAsPending( true );
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testUpdateOnTransactionIdle() {
+
+ $callback = function( $callback ) {
+ return call_user_func( $callback );
+ };
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( $callback ) );
+
+ $this->testEnvironment->clearPendingDeferredUpdates();
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->waitOnTransactionIdle();
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testCommitWithTransactionTicketOnDeferrableUpdate() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'getEmptyTransactionTicket' );
+
+ $this->testEnvironment->clearPendingDeferredUpdates();
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->isDeferrableUpdate( true );
+ $instance->commitWithTransactionTicket();
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testCommitWithTransactionTicketOnNonDeferrableUpdate() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->never() )
+ ->method( 'getEmptyTransactionTicket' );
+
+ $this->testEnvironment->clearPendingDeferredUpdates();
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->once() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->isDeferrableUpdate( false );
+ $instance->commitWithTransactionTicket();
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testCancelOnRollback() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->never() )
+ ->method( 'getEmptyTransactionTicket' );
+
+ $this->testEnvironment->clearPendingDeferredUpdates();
+
+ $test = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doTest' ] )
+ ->getMock();
+
+ $test->expects( $this->never() )
+ ->method( 'doTest' );
+
+ $callback = function() use ( $test ) {
+ $test->doTest();
+ };
+
+ $instance = new TransactionalCallableUpdate(
+ $callback,
+ $connection
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->isDeferrableUpdate( false );
+ $instance->commitWithTransactionTicket();
+
+ // #3765
+ $instance->cancelOnRollback( \SMW\MediaWiki\Database::TRIGGER_ROLLBACK );
+
+ $instance->pushUpdate();
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/EditInfoProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/EditInfoProviderTest.php
new file mode 100644
index 00000000..8aa4a60b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/EditInfoProviderTest.php
@@ -0,0 +1,274 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use ParserOutput;
+use SMW\MediaWiki\EditInfoProvider;
+
+/**
+ * @covers \SMW\MediaWiki\EditInfoProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class EditInfoProviderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\EditInfoProvider',
+ new EditInfoProvider( $wikiPage, $revision, $user )
+ );
+ }
+
+ /**
+ * @dataProvider wikiPageDataProvider
+ */
+ public function testFetchContentInfo( $parameters, $expected ) {
+
+ $instance = new EditInfoProvider(
+ $parameters['wikiPage'],
+ $parameters['revision']
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->fetchEditInfo()->getOutput()
+ );
+ }
+
+ public function testFetchSemanticData() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editInfo = (object)[];
+ $editInfo->output = new ParserOutput();
+ $editInfo->output->setExtensionData( \SMW\ParserData::DATA_ID, $semanticData );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareContentForEdit' )
+ ->will( $this->returnValue( $editInfo ) );
+
+ $instance = new EditInfoProvider(
+ $wikiPage,
+ $this->newRevisionStub()
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $instance->fetchSemanticData()
+ );
+ }
+
+ /**
+ * @dataProvider wikiPageDataProvider
+ */
+ public function testFetchContentInfoWithDisabledContentHandler( $parameters, $expected ) {
+
+ if ( !method_exists( '\WikiPage', 'prepareTextForEdit' ) ) {
+ $this->markTestSkipped( 'WikiPage::prepareTextForEdit is no longer accessible (MW 1.29+)' );
+ }
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->setConstructorArgs( [
+ $parameters['wikiPage'],
+ $parameters['revision'],
+ null
+ ] )
+ ->setMethods( [ 'hasContentForEditMethod' ] )
+ ->getMock();
+
+ $instance->expects( $this->any() )
+ ->method( 'hasContentForEditMethod' )
+ ->will( $this->returnValue( false ) );
+
+ $this->assertEquals(
+ $expected,
+ $instance->fetchEditInfo()->getOutput()
+ );
+ }
+
+ public function wikiPageDataProvider() {
+
+ // 'WikiPage::prepareTextForEdit is no longer accessible (MW 1.29+)'
+ $prepareTextForEditExists = method_exists( '\WikiPage', 'prepareTextForEdit' );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ #0 No parserOutput object
+ $editInfo = (object)[];
+ $editInfo->output = null;
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->setConstructorArgs( [ $title ] )
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareContentForEdit' )
+ ->will( $this->returnValue( $editInfo ) );
+
+ if ( $prepareTextForEditExists ) {
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareTextForEdit' )
+ ->will( $this->returnValue( $editInfo ) );
+ }
+
+ $provider[] = [
+ [
+ 'editInfo' => $editInfo,
+ 'wikiPage' => $wikiPage,
+ 'revision' => $this->newRevisionStub()
+ ],
+ null
+ ];
+
+ #1
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->setConstructorArgs( [ $title ] )
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareContentForEdit' )
+ ->will( $this->returnValue( false ) );
+
+ if ( $prepareTextForEditExists ) {
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareTextForEdit' )
+ ->will( $this->returnValue( false ) );
+ }
+
+ $provider[] = [
+ [
+ 'editInfo' => false,
+ 'wikiPage' => $wikiPage,
+ 'revision' => $this->newRevisionStub()
+ ],
+ null
+ ];
+
+ #2
+ $editInfo = (object)[];
+ $editInfo->output = new ParserOutput();
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->setConstructorArgs( [ $title ] )
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareContentForEdit' )
+ ->will( $this->returnValue( $editInfo ) );
+
+ if ( $prepareTextForEditExists ) {
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareTextForEdit' )
+ ->will( $this->returnValue( $editInfo ) );
+ }
+
+ $provider[] = [
+ [
+ 'editInfo' => $editInfo,
+ 'wikiPage' => $wikiPage,
+ 'revision' => $this->newRevisionStub()
+ ],
+ $editInfo->output
+ ];
+
+ #3
+ $editInfo = (object)[];
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->setConstructorArgs( [ $title ] )
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareContentForEdit' )
+ ->will( $this->returnValue( $editInfo ) );
+
+ if ( $prepareTextForEditExists ) {
+ $wikiPage->expects( $this->any() )
+ ->method( 'prepareTextForEdit' )
+ ->will( $this->returnValue( $editInfo ) );
+ }
+
+ $provider[] = [
+ [
+ 'editInfo' => $editInfo,
+ 'wikiPage' => $wikiPage,
+ 'revision' => $this->newRevisionStub()
+ ],
+ null
+ ];
+
+ return $provider;
+ }
+
+ private function newRevisionStub() {
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRawText', 'getContent' ] )
+ ->getMock();
+
+ $revision->expects( $this->any() )
+ ->method( 'getRawText' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $revision->expects( $this->any() )
+ ->method( 'getContent' )
+ ->will( $this->returnValueMap( [
+ [ \Revision::RAW, null, 'Foo' ],
+ [ \Revision::FOR_PUBLIC, null, $this->newContentStub() ],
+ ] ) );
+
+ return $revision;
+ }
+
+ private function newContentStub() {
+
+ if ( !class_exists( 'ContentHandler' ) ) {
+ return null;
+ }
+
+ $contentHandler = $this->getMockBuilder( '\ContentHandler' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentHandler->expects( $this->atLeastOnce() )
+ ->method( 'getDefaultFormat' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $content = $this->getMockBuilder( '\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content->expects( $this->atLeastOnce() )
+ ->method( 'getContentHandler' )
+ ->will( $this->returnValue( $contentHandler ) );
+
+ return $content;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Exception/ExtendedPermissionsErrorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Exception/ExtendedPermissionsErrorTest.php
new file mode 100644
index 00000000..ae5ebd2b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Exception/ExtendedPermissionsErrorTest.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Exception;
+
+use SMW\MediaWiki\Exception\ExtendedPermissionsError;
+
+/**
+ * @covers \SMW\MediaWiki\Exception\ExtendedPermissionsError
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ExtendedPermissionsErrorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Exception\ExtendedPermissionsError',
+ new ExtendedPermissionsError( 'Foo' )
+ );
+
+ $this->assertInstanceOf(
+ '\PermissionsError',
+ new ExtendedPermissionsError( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleDeleteTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleDeleteTest.php
new file mode 100644
index 00000000..0bbdbddd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleDeleteTest.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Hooks\ArticleDelete;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ArticleDelete
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ArticleDeleteTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $jobFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment(
+ [
+ 'smwgEnableUpdateJobs' => false,
+ 'smwgEnabledDeferredUpdate' => false
+ ]
+ );
+
+ $this->jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobFactory', $this->jobFactory );
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new ArticleDelete( $store );
+
+ $this->assertInstanceOf(
+ ArticleDelete::class,
+ $instance
+ );
+ }
+
+ public function testProcess() {
+
+ $idTable = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $updateDispatcherJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\UpdateDispatcherJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserCachePurgeJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\NullJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->atLeastOnce() )
+ ->method( 'newUpdateDispatcherJob' )
+ ->will( $this->returnValue( $updateDispatcherJob ) );
+
+ $this->jobFactory->expects( $this->atLeastOnce() )
+ ->method( 'newParserCachePurgeJob' )
+ ->will( $this->returnValue( $parserCachePurgeJob ) );
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'deleteSubject' );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getInProperties' )
+ ->will( $this->returnValue( [ new DIProperty( 'Foo' ) ] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $subject->getTitle() ) );
+
+ $instance = new ArticleDelete(
+ $store
+ );
+
+ $this->assertTrue(
+ $instance->process( $wikiPage )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleFromTitleTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleFromTitleTest.php
new file mode 100644
index 00000000..ead34554
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleFromTitleTest.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\ArticleFromTitle;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ArticleFromTitle
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ArticleFromTitleTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ArticleFromTitle::class,
+ new ArticleFromTitle( $this->store )
+ );
+ }
+
+ /**
+ * @dataProvider namespaceProvider
+ */
+ public function testProcess( $namespace, $expected ) {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( $namespace ) );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ArticleFromTitle( $this->store );
+ $instance->process( $title, $wikiPage );
+
+ $this->assertInstanceOf(
+ $expected,
+ $wikiPage
+ );
+ }
+
+ public function namespaceProvider() {
+
+ $provider[] = [
+ SMW_NS_PROPERTY,
+ 'SMW\Page\PropertyPage'
+ ];
+
+ $provider[] = [
+ SMW_NS_CONCEPT,
+ 'SMW\Page\ConceptPage'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleProtectCompleteTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleProtectCompleteTest.php
new file mode 100644
index 00000000..40cec922
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleProtectCompleteTest.php
@@ -0,0 +1,207 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\DataItemFactory;
+use SMW\MediaWiki\Hooks\ArticleProtectComplete;
+use SMW\PropertyAnnotators\EditProtectedPropertyAnnotator;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ArticleProtectComplete
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ArticleProtectCompleteTest extends \PHPUnit_Framework_TestCase {
+
+ private $spyLogger;
+ private $testEnvironment;
+ private $semanticDataFactory;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->spyLogger = $this->testEnvironment->getUtilityFactory()->newSpyLogger();
+ $this->semanticDataFactory = $this->testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ArticleProtectComplete::class,
+ new ArticleProtectComplete( $title, $editInfoProvider )
+ );
+ }
+
+ public function testProcessOnSelfInvokedReason() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ArticleProtectComplete(
+ $title,
+ $editInfoProvider
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $protections = [];
+ $reason = \SMW\Message::get( 'smw-edit-protection-auto-update' );
+
+ $instance->process( $protections, $reason );
+
+ $this->assertContains(
+ 'No changes required, invoked by own process',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testProcessOnMatchableEditProtectionToAddAnnotation() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_SPECIAL ) );
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editInfoProvider->expects( $this->once() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $instance = new ArticleProtectComplete(
+ $title,
+ $editInfoProvider
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->setOptions(
+ [
+ 'smwgEditProtectionRight' => 'Foo'
+ ]
+ );
+
+ $protections = [ 'edit' => 'Foo' ];
+ $reason = '';
+
+ $instance->process( $protections, $reason );
+
+ $this->assertContains(
+ 'ArticleProtectComplete addProperty `Is edit protected`',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testProcessOnUnmatchableEditProtectionToRemoveAnnotation() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ $this->dataItemFactory->newDIWikiPage( __METHOD__, NS_SPECIAL )
+ );
+
+ $dataItem = $this->dataItemFactory->newDIBoolean( true );
+ $dataItem->setOption( EditProtectedPropertyAnnotator::SYSTEM_ANNOTATION, true );
+
+ $semanticData->addPropertyObjectValue(
+ $this->dataItemFactory->newDIProperty( '_EDIP' ),
+ $dataItem
+ );
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_SPECIAL ) );
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editInfoProvider->expects( $this->once() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $instance = new ArticleProtectComplete(
+ $title,
+ $editInfoProvider
+ );
+
+ $instance->setLogger( $this->spyLogger );
+
+ $instance->setOptions(
+ [
+ 'smwgEditProtectionRight' => 'Foo2'
+ ]
+ );
+
+ $protections = [ 'edit' => 'Foo' ];
+ $reason = '';
+
+ $instance->process( $protections, $reason );
+
+ $this->assertContains(
+ 'ArticleProtectComplete removeProperty `Is edit protected`',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticlePurgeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticlePurgeTest.php
new file mode 100644
index 00000000..294da778
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticlePurgeTest.php
@@ -0,0 +1,218 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\Factbox\FactboxCache;
+use SMW\MediaWiki\Hooks\ArticlePurge;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockTitle;
+use WikiPage;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ArticlePurge
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ArticlePurgeTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+ private $testEnvironment;
+ private $cache;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $settings = [
+ 'smwgFactboxUseCache' => true,
+ 'smwgMainCacheType' => 'hash'
+ ];
+
+ $this->testEnvironment = new TestEnvironment( $settings );
+
+ $this->cache = $this->applicationFactory->newCacheFactory()->newFixedInMemoryCache();
+ $this->applicationFactory->registerObject( 'Cache', $this->cache );
+ }
+
+ public function tearDown() {
+ $this->applicationFactory->clear();
+ $this->testEnvironment->tearDown();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Hooks\ArticlePurge',
+ new ArticlePurge( $wikiPage )
+ );
+ }
+
+ /**
+ * @dataProvider titleDataProvider
+ */
+ public function testProcess( $setup, $expected ) {
+
+ $wikiPage = new WikiPage( $setup['title'] );
+ $pageId = $wikiPage->getTitle()->getArticleID();
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgAutoRefreshOnPurge',
+ $setup['smwgAutoRefreshOnPurge']
+ );
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgFactboxFeatures',
+ SMW_FACTBOX_PURGE_REFRESH
+ );
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgQueryResultCacheRefreshOnPurge',
+ $setup['smwgQueryResultCacheRefreshOnPurge']
+ );
+
+ $instance = new ArticlePurge();
+
+ $cacheFactory = $this->applicationFactory->newCacheFactory();
+ $factboxCacheKey = \SMW\Factbox\CachedFactbox::makeCacheKey( $pageId );
+ $purgeCacheKey = $cacheFactory->getPurgeCacheKey( $pageId );
+
+ $this->assertEquals(
+ $expected['autorefreshPreProcess'],
+ $this->cache->fetch( $purgeCacheKey ),
+ 'Asserts the autorefresh cache status before processing'
+ );
+
+ // Travis 210.5, 305.3
+ $travis = $this->cache->fetch( $factboxCacheKey );
+ $travisText = json_encode( $travis );
+ $this->assertEquals(
+ $expected['factboxPreProcess'],
+ $travis,
+ "Asserts the factbox cache status before processing, {$travisText}"
+ );
+
+ $this->assertFalse(
+ $this->cache->fetch( $purgeCacheKey ),
+ 'Asserts that before processing ...'
+ );
+
+ $result = $instance->process( $wikiPage );
+
+ // Post-process check
+ $this->assertTrue(
+ $result
+ );
+
+ $this->assertEquals(
+ $expected['autorefreshPostProcess'],
+ $this->cache->fetch( $purgeCacheKey ),
+ 'Asserts the autorefresh cache status after processing'
+ );
+
+ $this->assertEquals(
+ $expected['factboxPostProcess'],
+ $this->cache->fetch( $factboxCacheKey ),
+ 'Asserts the factbox cache status after processing'
+ );
+ }
+
+ public function titleDataProvider() {
+
+ $validIdTitle = MockTitle::buildMock( 'validIdTitle' );
+
+ $validIdTitle->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 9999 ) );
+
+ #0 Id = cache
+ $provider[] = [
+ [
+ 'title' => $validIdTitle,
+ 'smwgAutoRefreshOnPurge' => true,
+ 'smwgFactboxCacheRefreshOnPurge' => true,
+ 'smwgQueryResultCacheRefreshOnPurge' => false
+ ],
+ [
+ 'factboxPreProcess' => false,
+ 'autorefreshPreProcess' => false,
+ 'autorefreshPostProcess' => true,
+ 'factboxPostProcess' => false,
+ ]
+ ];
+
+ #1 Disabled setting
+ $validIdTitle = MockTitle::buildMock( 'Disabled' );
+
+ $validIdTitle->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 9099 ) );
+
+ $provider[] = [
+ [
+ 'title' => $validIdTitle,
+ 'smwgAutoRefreshOnPurge' => false,
+ 'smwgFactboxCacheRefreshOnPurge' => false,
+ 'smwgQueryResultCacheRefreshOnPurge' => false
+ ],
+ [
+ 'factboxPreProcess' => false,
+ 'autorefreshPreProcess' => false,
+ 'autorefreshPostProcess' => false,
+ 'factboxPostProcess' => false,
+ ]
+ ];
+
+ // #2 No Id
+ $nullIdTitle = MockTitle::buildMock( 'NullId' );
+
+ $nullIdTitle->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 0 ) );
+
+ $provider[] = [
+ [
+ 'title' => $nullIdTitle,
+ 'smwgAutoRefreshOnPurge' => true,
+ 'smwgFactboxCacheRefreshOnPurge' => true,
+ 'smwgQueryResultCacheRefreshOnPurge' => false
+ ],
+ [
+ 'factboxPreProcess' => false,
+ 'autorefreshPreProcess' => false,
+ 'autorefreshPostProcess' => false,
+ 'factboxPostProcess' => false,
+ ]
+ ];
+
+ #3 No Id
+ $provider[] = [
+ [
+ 'title' => $nullIdTitle,
+ 'smwgAutoRefreshOnPurge' => true,
+ 'smwgFactboxCacheRefreshOnPurge' => false,
+ 'smwgQueryResultCacheRefreshOnPurge' => false
+ ],
+ [
+ 'factboxPreProcess' => false,
+ 'autorefreshPreProcess' => false,
+ 'autorefreshPostProcess' => false,
+ 'factboxPostProcess' => false,
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleViewHeaderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleViewHeaderTest.php
new file mode 100644
index 00000000..cb1405f2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ArticleViewHeaderTest.php
@@ -0,0 +1,148 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Hooks\ArticleViewHeader;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ArticleViewHeader
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ArticleViewHeaderTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ArticleViewHeader::class,
+ new ArticleViewHeader( $this->store )
+ );
+ }
+
+ public function testProcessOnCategory() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__, NS_CATEGORY );
+ $property = new DIProperty( DIProperty::TYPE_CHANGE_PROP );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'hasProperty' )
+ ->with( $this->equalTo( $property ) )
+ ->will( $this->returnValue( true ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $output = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $output->expects( $this->once() )
+ ->method( 'addHtml' );
+
+ $context = $this->getMockBuilder( '\RequestContext' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $context->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $output ) );
+
+ $page = $this->getMockBuilder( '\Article' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $subject->getTitle() ) );
+
+ $page->expects( $this->any() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $context ) );
+
+ $instance = new ArticleViewHeader(
+ $this->store
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgChangePropagationWatchlist' => [ '_SUBC' ]
+ ]
+ );
+
+ $outputDone = '';
+ $useParserCache = '';
+
+ $instance->process( $page, $outputDone, $useParserCache );
+
+ $this->assertFalse(
+ $useParserCache
+ );
+ }
+
+ public function testProcessOnNoCategory() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $output = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page = $this->getMockBuilder( '\Article' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $subject->getTitle() ) );
+
+ $page->expects( $this->never() )
+ ->method( 'getContext' );
+
+ $instance = new ArticleViewHeader(
+ $this->store
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgChangePropagationWatchlist' => [ '_SUBC' ]
+ ]
+ );
+
+ $outputDone = '';
+ $useParserCache = '';
+
+ $instance->process( $page, $outputDone, $useParserCache );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BaseTemplateToolboxTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BaseTemplateToolboxTest.php
new file mode 100644
index 00000000..765ec71a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BaseTemplateToolboxTest.php
@@ -0,0 +1,237 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\BaseTemplateToolbox;
+use SMW\Tests\Utils\Mock\MockTitle;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\BaseTemplateToolbox
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class BaseTemplateToolboxTest extends \PHPUnit_Framework_TestCase {
+
+ private $namespaceExaminer;
+ private $skinTemplate;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ BaseTemplateToolbox::class,
+ new BaseTemplateToolbox( $this->namespaceExaminer )
+ );
+ }
+
+ /**
+ * @dataProvider skinTemplateDataProvider
+ */
+ public function testProcess( $setup, $expected ) {
+
+ $this->namespaceExaminer->expects( $this->any() )
+ ->method( 'isSemanticEnabled' )
+ ->will( $this->returnValue( $setup['settings']['isEnabledNamespace'] ) );
+
+ $toolbox = [];
+
+ $instance = new BaseTemplateToolbox(
+ $this->namespaceExaminer
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgBrowseFeatures' => $setup['settings']['smwgBrowseFeatures']
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->process( $setup['skinTemplate'], $toolbox )
+ );
+
+ if ( $expected['count'] == 0 ) {
+ $this->assertEmpty( $toolbox );
+ } else {
+ $this->assertCount(
+ $expected['count'],
+ $toolbox['smw-browse']
+ );
+ }
+ }
+
+ public function skinTemplateDataProvider() {
+
+ #0 Standard title
+ $settings = [
+ 'isEnabledNamespace' => true,
+ 'smwgBrowseFeatures' => SMW_BROWSE_TLINK
+ ];
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $this->newSkinStub() ) );
+
+ $skinTemplate->data['isarticle'] = true;
+
+ $provider[] = [
+ [
+ 'skinTemplate' => $skinTemplate,
+ 'settings' => $settings
+ ],
+ [ 'count' => 4 ],
+ ];
+
+ #1 isarticle = false
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $this->newSkinStub() ) );
+
+ $skinTemplate->data['isarticle'] = false;
+
+ $provider[] = [
+ [
+ 'skinTemplate' => $skinTemplate,
+ 'settings' => $settings
+ ],
+ [ 'count' => 0 ],
+ ];
+
+ #2 smwgBrowseFeatures = false
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $this->newSkinStub() ) );
+
+ $skinTemplate->data['isarticle'] = true;
+
+ $settings = [
+ 'isEnabledNamespace' => true,
+ 'smwgBrowseFeatures' => SMW_BROWSE_NONE
+ ];
+
+ $provider[] = [
+ [
+ 'skinTemplate' => $skinTemplate,
+ 'settings' => $settings
+ ],
+ [ 'count' => 0 ],
+ ];
+
+ #3 smwgNamespacesWithSemanticLinks = false
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $this->newSkinStub() ) );
+
+ $skinTemplate->data['isarticle'] = true;
+
+ $settings = [
+ 'isEnabledNamespace' => false,
+ 'smwgBrowseFeatures' => SMW_BROWSE_TLINK
+ ];
+
+ $provider[] = [
+ [
+ 'skinTemplate' => $skinTemplate,
+ 'settings' => $settings
+ ],
+ [ 'count' => 0 ],
+ ];
+
+ #4 Special page
+ $settings = [
+ 'isEnabledNamespace' => true,
+ 'smwgBrowseFeatures' => SMW_BROWSE_TLINK
+ ];
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $skin ) );
+
+ $skinTemplate->data['isarticle'] = true;
+
+ $provider[] = [
+ [
+ 'skinTemplate' => $skinTemplate,
+ 'settings' => $settings
+ ],
+ [ 'count' => 0 ],
+ ];
+
+ return $provider;
+ }
+
+ private function newSkinStub() {
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( Title::newFromText( __METHOD__ ) ) );
+
+ $skin->expects( $this->any() )
+ ->method( 'msg' )
+ ->will( $this->returnValue( $message ) );
+
+ return $skin;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforeDisplayNoArticleTextTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforeDisplayNoArticleTextTest.php
new file mode 100644
index 00000000..dbbc40f2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforeDisplayNoArticleTextTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\BeforeDisplayNoArticleText;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\BeforeDisplayNoArticleText
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class BeforeDisplayNoArticleTextTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\BeforeDisplayNoArticleText',
+ new BeforeDisplayNoArticleText( $wikiPage )
+ );
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testPerformUpdate( $namespace, $text, $expected ) {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( $text ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( $namespace ) );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new BeforeDisplayNoArticleText( $wikiPage );
+
+ $this->assertEquals( $expected, $instance->process() );
+ }
+
+ public function titleProvider() {
+
+ $provider = [
+ [ SMW_NS_PROPERTY, 'Modification date', false ],
+ [ SMW_NS_PROPERTY, 'Foo', true ],
+ [ NS_MAIN, 'Modification date', true ],
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforePageDisplayTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforePageDisplayTest.php
new file mode 100644
index 00000000..3c025f01
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/BeforePageDisplayTest.php
@@ -0,0 +1,182 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\BeforePageDisplay;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\BeforePageDisplay
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class BeforePageDisplayTest extends \PHPUnit_Framework_TestCase {
+
+ private $outputPage;
+ private $request;
+ private $skin;
+
+ protected function setUp() {
+
+ $this->request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $requestContext = $this->getMockBuilder( '\RequestContext' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $requestContext->expects( $this->any() )
+ ->method( 'getRequest' )
+ ->will( $this->returnValue( $this->request ) );
+
+ $this->outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->skin->expects( $this->any() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $requestContext ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ BeforePageDisplay::class,
+ new BeforePageDisplay()
+ );
+ }
+
+ public function testModules() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->any() )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( 'smw-prefs-general-options-suggester-textinput' ) )
+ ->will( $this->returnValue( true ) );
+
+ $this->outputPage->expects( $this->exactly( 2 ) )
+ ->method( 'addModules' );
+
+ $this->outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $instance = new BeforePageDisplay();
+
+ $instance->process( $this->outputPage, $this->skin );
+ }
+
+ public function testPrependHTML_InstallerIncompleteTasks() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputPage->expects( $this->atLeastOnce() )
+ ->method( 'prependHTML' );
+
+ $this->outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $instance = new BeforePageDisplay();
+
+ $instance->setOptions(
+ [
+ 'installer.incomplete_tasks' => [ 'Foo', 'Bar' ]
+ ]
+ );
+
+ $instance->process( $this->outputPage, $this->skin );
+ }
+
+ /**
+ * @dataProvider titleDataProvider
+ */
+ public function testProcess( $setup, $expected ) {
+
+ $expected = $expected['result'] ? $this->atLeastOnce() : $this->never();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $this->outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $setup['title'] ) );
+
+ $this->outputPage->expects( $expected )
+ ->method( 'addLink' );
+
+ $instance = new BeforePageDisplay();
+
+ $this->assertTrue(
+ $instance->process( $this->outputPage, $this->skin )
+ );
+ }
+
+ public function titleDataProvider() {
+
+ #0 Standard title
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPrefixedText' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( false ) );
+
+ $provider[] = [
+ [
+ 'title' => $title
+ ],
+ [
+ 'result' => true
+ ]
+ ];
+
+ #1 as SpecialPage
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $provider[] = [
+ [
+ 'title' => $title
+ ],
+ [
+ 'result' => false
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/EditPageFormTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/EditPageFormTest.php
new file mode 100644
index 00000000..b93dbedd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/EditPageFormTest.php
@@ -0,0 +1,161 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\EditPageForm;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\EditPageForm
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class EditPageFormTest extends \PHPUnit_Framework_TestCase {
+
+ private $namespaceExaminer;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\EditPageForm',
+ new EditPageForm( $this->namespaceExaminer )
+ );
+ }
+
+ public function testDisabledHelp() {
+
+ $editPage = $this->getMockBuilder( '\EditPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new EditPageForm(
+ $this->namespaceExaminer
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgEnabledEditPageHelp' => false
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->process( $editPage )
+ );
+ }
+
+ public function testDisabledOnUserPreference() {
+
+ $editPage = $this->getMockBuilder( '\EditPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new EditPageForm(
+ $this->namespaceExaminer
+ );
+
+ $instance->setOptions(
+ [
+ 'prefs-disable-editpage' => true
+ ]
+ );
+
+ $editPage->editFormPageTop = '';
+
+ $instance->process( $editPage );
+
+ $this->assertEmpty(
+ $editPage->editFormPageTop
+ );
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testExtendEditFormPageTop( $title, $namespaces, $isSemanticEnabled, $expected ) {
+
+ $this->namespaceExaminer->expects( $this->any() )
+ ->method( 'isSemanticEnabled' )
+ ->with( $this->equalTo( $namespaces ) )
+ ->will( $this->returnValue( $isSemanticEnabled ) );
+
+ $editPage = $this->getMockBuilder( '\EditPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $editPage->editFormPageTop = '';
+
+ $instance = new EditPageForm(
+ $this->namespaceExaminer
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgEnabledEditPageHelp' => true
+ ]
+ );
+
+ $instance->process( $editPage );
+
+ $this->assertContains(
+ $expected,
+ $editPage->editFormPageTop
+ );
+ }
+
+ public function titleProvider() {
+
+ $provider[] = [
+ Title::newFromText( 'Foo', SMW_NS_PROPERTY ),
+ SMW_NS_PROPERTY,
+ true,
+ 'smw-editpage-property-annotation-enabled'
+ ];
+
+ $provider[] = [
+ Title::newFromText( 'Modification date', SMW_NS_PROPERTY ),
+ SMW_NS_PROPERTY,
+ true,
+ 'smw-editpage-property-annotation-disabled'
+ ];
+
+ $provider[] = [
+ Title::newFromText( 'Foo', SMW_NS_CONCEPT ),
+ SMW_NS_CONCEPT,
+ true,
+ 'smw-editpage-concept-annotation-enabled'
+ ];
+
+ $provider[] = [
+ Title::newFromText( 'Foo', NS_MAIN ),
+ NS_MAIN,
+ true,
+ 'smw-editpage-annotation-enabled'
+ ];
+
+ $provider[] = [
+ Title::newFromText( 'Foo', NS_MAIN ),
+ NS_MAIN,
+ false,
+ 'smw-editpage-annotation-disabled'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionSchemaUpdatesTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionSchemaUpdatesTest.php
new file mode 100644
index 00000000..fa4f09e5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionSchemaUpdatesTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\ExtensionSchemaUpdates;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ExtensionSchemaUpdates
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ExtensionSchemaUpdatesTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $databaseUpdater = $this->getMockBuilder( '\DatabaseUpdater' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\ExtensionSchemaUpdates',
+ new ExtensionSchemaUpdates( $databaseUpdater )
+ );
+ }
+
+ public function testProcess() {
+
+ $databaseUpdater = $this->getMockBuilder( '\DatabaseUpdater' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'addExtensionUpdate' ] )
+ ->getMockForAbstractClass();
+
+ $databaseUpdater->expects( $this->once() )
+ ->method( 'addExtensionUpdate' );
+
+ $instance = new ExtensionSchemaUpdates( $databaseUpdater );
+ $instance->process();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionTypesTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionTypesTest.php
new file mode 100644
index 00000000..6caf026a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ExtensionTypesTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\ExtensionTypes;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ExtensionTypes
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ExtensionTypesTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ExtensionTypes::class,
+ new ExtensionTypes()
+ );
+ }
+
+ public function testProcess() {
+
+ $extensionTypes = [];
+
+ $instance = new ExtensionTypes();
+ $instance->process( $extensionTypes );
+
+ $this->assertArrayHasKey(
+ 'semantic',
+ $extensionTypes
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/FileUploadTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/FileUploadTest.php
new file mode 100644
index 00000000..a8e38e70
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/FileUploadTest.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use ParserOutput;
+use SMW\MediaWiki\Hooks\FileUpload;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\FileUpload
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class FileUploadTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment( [
+ 'smwgPageSpecialProperties' => [ '_MEDIA', '_MIME' ],
+ 'smwgNamespacesWithSemanticLinks' => [ NS_FILE => true ],
+ 'smwgMainCacheType' => 'hash',
+ 'smwgEnableUpdateJobs' => false
+ ] );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ FileUpload::class,
+ new FileUpload( $namespaceExaminer )
+ );
+ }
+
+ public function testprocessEnabledNamespace() {
+
+ $title = Title::newFromText( __METHOD__, NS_FILE );
+
+ $namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $namespaceExaminer->expects( $this->atLeastOnce() )
+ ->method( 'isSemanticEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $file = $this->getMockBuilder( '\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $file->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $wikiFilePage = $this->getMockBuilder( '\WikiFilePage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiFilePage->expects( $this->once() )
+ ->method( 'getParserOutput' )
+ ->will( $this->returnValue( new ParserOutput() ) );
+
+ $wikiFilePage->expects( $this->atLeastOnce() )
+ ->method( 'getFile' )
+ ->will( $this->returnValue( $file ) );
+
+ $pageCreator = $this->getMockBuilder( 'SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'createFilePage' ] )
+ ->getMock();
+
+ $pageCreator->expects( $this->once() )
+ ->method( 'createFilePage' )
+ ->with( $this->equalTo( $title ) )
+ ->will( $this->returnValue( $wikiFilePage ) );
+
+ $this->testEnvironment->registerObject( 'PageCreator', $pageCreator );
+
+ $instance = new FileUpload(
+ $namespaceExaminer
+ );
+
+ $reUploadStatus = true;
+
+ $this->assertTrue(
+ $instance->process( $file, $reUploadStatus )
+ );
+
+ $this->assertEquals(
+ $wikiFilePage->smwFileReUploadStatus,
+ $reUploadStatus
+ );
+ }
+
+ public function testTryToProcessDisabledNamespace() {
+
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+
+ $namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $namespaceExaminer->expects( $this->atLeastOnce() )
+ ->method( 'isSemanticEnabled' )
+ ->will( $this->returnValue( false ) );
+
+ $file = $this->getMockBuilder( 'File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $file->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $pageCreator = $this->getMockBuilder( 'SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $this->never() ) // <-- never
+ ->method( 'createFilePage' );
+
+ $this->testEnvironment->registerObject( 'PageCreator', $pageCreator );
+
+ $instance = new FileUpload(
+ $namespaceExaminer
+ );
+
+ $instance->process( $file, false );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/GetPreferencesTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/GetPreferencesTest.php
new file mode 100644
index 00000000..33dee2ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/GetPreferencesTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\GetPreferences;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\GetPreferences
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class GetPreferencesTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $preferences = [];
+
+ $this->assertInstanceOf(
+ GetPreferences::class,
+ new GetPreferences( $user )
+ );
+ }
+
+ /**
+ * @dataProvider keyProvider
+ */
+ public function testProcess( $key ) {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $preferences = [];
+
+ $instance = new GetPreferences( $user );
+
+ $instance->setOptions(
+ [
+ 'smwgEnabledEditPageHelp' => false
+ ]
+ );
+
+ $instance->process( $preferences );
+
+ $this->assertArrayHasKey(
+ $key,
+ $preferences
+ );
+ }
+
+ public function keyProvider() {
+
+ $provider[] = [
+ 'smw-prefs-intro'
+ ];
+
+ $provider[] = [
+ 'smw-prefs-ask-options-tooltip-display'
+ ];
+
+ $provider[] = [
+ 'smw-prefs-general-options-time-correction'
+ ];
+
+ $provider[] = [
+ 'smw-prefs-general-options-disable-editpage-info'
+ ];
+
+ $provider[] = [
+ 'smw-prefs-general-options-jobqueue-watchlist'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookHandlerTest.php
new file mode 100644
index 00000000..38f4635c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookHandlerTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\HookHandler;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\HookHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HookHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ HookHandler::class,
+ new HookHandler()
+ );
+ }
+
+ public function testOptions() {
+
+ $instance = new HookHandler();
+
+ $this->assertNull(
+ $instance->getOption( 'Foo' )
+ );
+
+ $this->assertFalse(
+ $instance->getOption( 'Foo', false )
+ );
+
+ $instance->setOptions( [ 'Foo' => 42 ] );
+
+ $this->assertEquals(
+ 42,
+ $instance->getOption( 'Foo' )
+ );
+
+ $this->assertTrue(
+ $instance->isFlagSet( 'Foo', 42 )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookListenerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookListenerTest.php
new file mode 100644
index 00000000..7af84c1e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookListenerTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\HookListener;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\HookListener
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HooksTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ HookListener::class,
+ new HookListener()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookRegistryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookRegistryTest.php
new file mode 100644
index 00000000..889d03b0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/HookRegistryTest.php
@@ -0,0 +1,1733 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Hooks\HookRegistry;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\HookRegistry
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class HookRegistryTest extends \PHPUnit_Framework_TestCase {
+
+ private $parser;
+ private $title;
+ private $outputPage;
+ private $requestContext;
+ private $skin;
+ private $store;
+ private $testEnvironment;
+
+ /**
+ * Has a static signature on purpose!
+ *
+ * @var array
+ */
+ private static $handlers = [];
+
+ protected function setUp() {
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $this->outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputPage->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestContext = $this->getMockBuilder( '\RequestContext' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestContext->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->outputPage ) );
+
+ $this->requestContext->expects( $this->any() )
+ ->method( 'getRequest' )
+ ->will( $this->returnValue( $webRequest ) );
+
+ $this->skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->skin->expects( $this->any() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $this->requestContext ) );
+
+ $this->skin->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->outputPage ) );
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $contentParser = $this->getMockBuilder( '\SMW\ContentParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentParser->expects( $this->any() )
+ ->method( 'parse' )
+ ->will( $this->returnValue( $this->parser ) );
+
+ $deferredCallableUpdate = $this->getMockBuilder( '\SMW\DeferredCallableUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ $this->testEnvironment->registerObject( 'ContentParser', $contentParser );
+ $this->testEnvironment->registerObject( 'DeferredCallableUpdate', $deferredCallableUpdate );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $vars = [];
+
+ $this->assertInstanceOf(
+ HookRegistry::class,
+ new HookRegistry( $vars, 'foo' )
+ );
+ }
+
+ public function testInitExtension() {
+
+ $vars = [];
+
+ HookRegistry::initExtension( $vars );
+
+ // CanonicalNamespaces
+ $callback = end( $vars['wgHooks']['CanonicalNamespaces'] );
+ $namespaces = [];
+
+ $this->assertThatHookIsExcutable(
+ $callback,
+ [ &$namespaces ]
+ );
+
+ // SpecialPage_initList
+ $callback = end( $vars['wgHooks']['SpecialPage_initList'] );
+ $specialPages = [];
+
+ $this->assertThatHookIsExcutable(
+ $callback,
+ [ &$specialPages ]
+ );
+
+ // ApiMain::moduleManager
+ $callback = end( $vars['wgHooks']['ApiMain::moduleManager'] );
+
+ $apiModuleManager = $this->getMockBuilder( '\ApiModuleManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertThatHookIsExcutable(
+ $callback,
+ [ $apiModuleManager ]
+ );
+ }
+
+ /**
+ * @dataProvider callMethodProvider
+ */
+ public function testRegister( $method ) {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $vars = [
+ 'IP' => 'bar',
+ 'wgVersion' => '1.24',
+ 'wgLang' => $language,
+ 'smwgEnabledDeferredUpdate' => false
+ ];
+
+ $instance = new HookRegistry( $vars, 'foo' );
+ $instance->register();
+
+ self::$handlers[] = call_user_func_array( [ $this, $method ], [ $instance ] );
+ }
+
+ /**
+ * @depends testRegister
+ */
+ public function testCheckOnMissingHandlers() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $vars = [
+ 'IP' => 'bar',
+ 'wgVersion' => '1.24',
+ 'wgLang' => $language,
+ 'smwgEnabledDeferredUpdate' => false
+ ];
+
+ $instance = new HookRegistry( $vars, 'foo' );
+ $instance->register();
+
+ $handlerList = $instance->getHandlerList();
+ $handlers = array_flip( self::$handlers );
+
+ foreach ( $handlerList as $handler ) {
+ $this->assertArrayHasKey( $handler, $handlers, "Missing a `$handler` test!" );
+ }
+
+ self::$handlers = [];
+ }
+
+ public function callMethodProvider() {
+
+ return [
+ [ 'callParserAfterTidy' ],
+ [ 'callBaseTemplateToolbox' ],
+ [ 'callSkinAfterContent' ],
+ [ 'callOutputPageParserOutput' ],
+ [ 'callBeforePageDisplay' ],
+ [ 'callSpecialSearchResultsPrepend' ],
+ [ 'callSpecialSearchProfiles' ],
+ [ 'callSpecialSearchProfileForm' ],
+ [ 'callInternalParseBeforeLinks' ],
+ [ 'callNewRevisionFromEditComplete' ],
+ [ 'callTitleMoveComplete' ],
+ [ 'callArticleProtectComplete' ],
+ [ 'callArticleViewHeader' ],
+ [ 'callArticlePurge' ],
+ [ 'callArticleDelete' ],
+ [ 'callLinksUpdateConstructed' ],
+ [ 'callSpecialStatsAddExtra' ],
+ [ 'callFileUpload' ],
+ [ 'callResourceLoaderGetConfigVars' ],
+ [ 'callGetPreferences' ],
+ [ 'callPersonalUrls' ],
+ [ 'callSkinTemplateNavigation' ],
+ [ 'callLoadExtensionSchemaUpdates' ],
+ [ 'callResourceLoaderTestModules' ],
+ [ 'callExtensionTypes' ],
+ [ 'callTitleIsAlwaysKnown' ],
+ [ 'callBeforeDisplayNoArticleText' ],
+ [ 'callArticleFromTitle' ],
+ [ 'callTitleIsMovable' ],
+ [ 'callContentHandlerForModelID' ],
+ [ 'callEditPageForm' ],
+ [ 'callParserOptionsRegister' ],
+ [ 'callParserFirstCallInit' ],
+ [ 'callTitleQuickPermissions' ],
+ [ 'callOutputPageCheckLastModified' ],
+ [ 'callIsFileCacheable' ],
+ [ 'callRejectParserCacheValue' ],
+ [ 'callSoftwareInfo' ],
+ [ 'callBlockIpComplete' ],
+ [ 'callUnblockUserComplete' ],
+ [ 'callUserGroupsChanged' ],
+ [ 'callSMWSQLStoreEntityReferenceCleanUpComplete' ],
+ [ 'callSMWAdminTaskHandlerFactory' ],
+ [ 'callSMWSQLStorAfterDataUpdateComplete' ],
+ [ 'callSMWStoreBeforeQueryResultLookupComplete' ],
+ [ 'callSMWStoreAfterQueryResultLookupComplete' ],
+ [ 'callSMWBrowseAfterIncomingPropertiesLookupComplete' ],
+ [ 'callSMWBrowseBeforeIncomingPropertyValuesFurtherLinkCreate' ],
+ [ 'callSMWSQLStoreInstallerAfterCreateTablesComplete' ],
+ ];
+ }
+
+ public function callParserAfterTidy( $instance ) {
+
+ $handler = 'ParserAfterTidy';
+
+ $this->title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $this->parser->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $text = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$this->parser, &$text ]
+ );
+
+ return $handler;
+ }
+
+ public function callBaseTemplateToolbox( $instance ) {
+
+ $handler = 'BaseTemplateToolbox';
+
+ $this->title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $this->skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->any() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $this->skin ) );
+
+ $toolbox = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $skinTemplate, &$toolbox ]
+ );
+
+ return $handler;
+ }
+
+ public function callSkinAfterContent( $instance ) {
+
+ $handler = 'SkinAfterContent';
+
+ $this->title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $this->skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $data = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$data, $this->skin ]
+ );
+
+ return $handler;
+ }
+
+ public function callOutputPageParserOutput( $instance ) {
+
+ $handler = 'OutputPageParserOutput';
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $this->outputPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$this->outputPage, $parserOutput ]
+ );
+
+ return $handler;
+ }
+
+ public function callBeforePageDisplay( $instance ) {
+
+ $handler = 'BeforePageDisplay';
+
+ $this->title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $this->outputPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$this->outputPage, &$this->skin ]
+ );
+
+ return $handler;
+ }
+
+ public function callSpecialSearchResultsPrepend( $instance ) {
+
+ $handler = 'SpecialSearchResultsPrepend';
+
+ $specialSearch = $this->getMockBuilder( '\SpecialSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $specialSearch, $this->outputPage, '' ]
+ );
+
+ return $handler;
+ }
+
+ public function callSpecialSearchProfiles( $instance ) {
+
+ $handler = 'SpecialSearchProfiles';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $profiles = [];
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$profiles ]
+ );
+
+ return $handler;
+ }
+
+ public function callSpecialSearchProfileForm( $instance ) {
+
+ $handler = 'SpecialSearchProfileForm';
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine = $this->getMockBuilder( '\SMW\MediaWiki\Search\Search' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $specialSearch = $this->getMockBuilder( '\SpecialSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $specialSearch->expects( $this->any() )
+ ->method( 'getSearchEngine' )
+ ->will( $this->returnValue( $searchEngine ) );
+
+ $specialSearch->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $specialSearch->expects( $this->any() )
+ ->method( 'getNamespaces' )
+ ->will( $this->returnValue( [] ) );
+
+ $specialSearch->expects( $this->any() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $this->requestContext ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $form = '';
+ $profile = 'smw';
+ $term = '';
+ $opts = [];
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $specialSearch, &$form, $profile, $term, $opts ]
+ );
+
+ return $handler;
+ }
+
+ public function callInternalParseBeforeLinks( $instance ) {
+
+ $handler = 'InternalParseBeforeLinks';
+
+ $this->title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $stripState = $this->getMockBuilder( '\StripState' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $text = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$parser, &$text, &$stripState ]
+ );
+
+ return $handler;
+ }
+
+ public function callNewRevisionFromEditComplete( $instance ) {
+
+ $handler = 'NewRevisionFromEditComplete';
+
+ $contentHandler = $this->getMockBuilder( '\ContentHandler' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content = $this->getMockBuilder( '\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content->expects( $this->any() )
+ ->method( 'getContentHandler' )
+ ->will( $this->returnValue( $contentHandler ) );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $revision->expects( $this->any() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( $content ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $baseId = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $wikiPage, $revision, $baseId, $user ]
+ );
+
+ return $handler;
+ }
+
+ public function callTitleMoveComplete( $instance ) {
+
+ $handler = 'TitleMoveComplete';
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'deleteSubject' ] )
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $oldTitle = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $oldTitle->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_SPECIAL ) );
+
+ $oldTitle->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $newTitle = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $newTitle->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_SPECIAL ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $oldId = 42;
+ $newId = 0;
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$oldTitle, &$newTitle, &$user, $oldId, $newId ]
+ );
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ return $handler;
+ }
+
+ public function callArticleProtectComplete( $instance ) {
+
+ $handler = 'ArticleProtectComplete';
+
+ $contentHandler = $this->getMockBuilder( '\ContentHandler' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content = $this->getMockBuilder( '\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content->expects( $this->any() )
+ ->method( 'getContentHandler' )
+ ->will( $this->returnValue( $contentHandler ) );
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $revision->expects( $this->any() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( $content ) );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getRevision' )
+ ->will( $this->returnValue( $revision ) );
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $protections = [];
+ $reason = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$wikiPage, &$user, $protections, $reason ]
+ );
+
+ return $handler;
+ }
+
+ public function callArticleViewHeader( $instance ) {
+
+ $handler = 'ArticleViewHeader';
+
+ $page = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $outputDone = '';
+ $useParserCache = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$page, &$outputDone, &$useParserCache ]
+ );
+
+ return $handler;
+ }
+
+ public function callArticlePurge( $instance ) {
+
+ $handler = 'ArticlePurge';
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$wikiPage ]
+ );
+
+ return $handler;
+ }
+
+ public function callArticleDelete( $instance ) {
+
+ $handler = 'ArticleDelete';
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubSemanticData' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reason = '';
+ $error = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$wikiPage, &$user, &$reason, &$error ]
+ );
+
+ return $handler;
+ }
+
+ public function callLinksUpdateConstructed( $instance ) {
+
+ $handler = 'LinksUpdateConstructed';
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'updateData' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->getOptions()->set( 'smwgSemanticsEnabled', false );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_SPECIAL ) );
+
+ $linksUpdate = $this->getMockBuilder( '\LinksUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $linksUpdate->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $linksUpdate->expects( $this->any() )
+ ->method( 'getParserOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $linksUpdate ]
+ );
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ return $handler;
+ }
+
+ public function callSpecialStatsAddExtra( $instance ) {
+
+ $handler = 'SpecialStatsAddExtra';
+
+ $extraStats = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$extraStats ]
+ );
+
+ return $handler;
+ }
+
+ public function callFileUpload( $instance ) {
+
+ $handler = 'FileUpload';
+
+ $file = $this->getMockBuilder( '\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reupload = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $file, $reupload ]
+ );
+
+ return $handler;
+ }
+
+ public function callResourceLoaderGetConfigVars( $instance ) {
+
+ $handler = 'ResourceLoaderGetConfigVars';
+
+ $vars = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$vars ]
+ );
+
+ return $handler;
+ }
+
+ public function callGetPreferences( $instance ) {
+
+ $handler = 'GetPreferences';
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $preferences = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $user, &$preferences ]
+ );
+
+ return $handler;
+ }
+
+ public function callPersonalUrls( $instance ) {
+
+ $handler = 'PersonalUrls';
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $personal_urls = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$personal_urls, $title, $skinTemplate ]
+ );
+
+ return $handler;
+ }
+
+ public function callSkinTemplateNavigation( $instance ) {
+
+ $handler = 'SkinTemplateNavigation';
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $links = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$skinTemplate, &$links ]
+ );
+
+ return $handler;
+ }
+
+ public function callLoadExtensionSchemaUpdates( $instance ) {
+
+ $handler = 'LoadExtensionSchemaUpdates';
+
+ $databaseUpdater = $this->getMockBuilder( '\DatabaseUpdater' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $databaseUpdater ]
+ );
+
+ return $handler;
+ }
+
+ public function callResourceLoaderTestModules( $instance ) {
+
+ $handler = 'ResourceLoaderTestModules';
+
+ $resourceLoader = $this->getMockBuilder( '\ResourceLoader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $testModules = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$testModules, &$resourceLoader ]
+ );
+
+ return $handler;
+ }
+
+ public function callExtensionTypes( $instance ) {
+
+ $handler = 'ExtensionTypes';
+
+ $extTypes = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$extTypes ]
+ );
+
+ return $handler;
+ }
+
+ public function callTitleIsAlwaysKnown( $instance ) {
+
+ $handler = 'TitleIsAlwaysKnown';
+
+ $result = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $this->title, &$result ]
+ );
+
+ return $handler;
+ }
+
+ public function callBeforeDisplayNoArticleText( $instance ) {
+
+ $handler = 'BeforeDisplayNoArticleText';
+
+ $article = $this->getMockBuilder( '\Article' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $article->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $article ]
+ );
+
+ return $handler;
+ }
+
+ public function callArticleFromTitle( $instance ) {
+
+ $handler = 'ArticleFromTitle';
+
+ $article = $this->getMockBuilder( '\Article' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $article->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$this->title, &$article ]
+ );
+
+ return $handler;
+ }
+
+ public function callTitleIsMovable( $instance ) {
+
+ $handler = 'TitleIsMovable';
+
+ $isMovable = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $this->title, &$isMovable ]
+ );
+
+ return $handler;
+ }
+
+ public function callContentHandlerForModelID( $instance ) {
+
+ $handler = 'ContentHandlerForModelID';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $modelId = 'smw/schema';
+ $contentHandler = '';
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $modelId, &$contentHandler ]
+ );
+
+ return $handler;
+ }
+
+ public function callEditPageForm( $instance ) {
+
+ $handler = 'EditPage::showEditForm:initial';
+
+ $title = Title::newFromText( 'Foo' );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editPage = $this->getMockBuilder( '\EditPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $editPage, $outputPage ]
+ );
+
+ return $handler;
+ }
+
+ public function callParserOptionsRegister( $instance ) {
+
+ $handler = 'ParserOptionsRegister';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $defaults = [];
+ $inCacheKey = [];
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$defaults, &$inCacheKey ]
+ );
+
+ return $handler;
+ }
+
+ public function callParserFirstCallInit( $instance ) {
+
+ $handler = 'ParserFirstCallInit';
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$parser ]
+ );
+
+ return $handler;
+ }
+
+ public function callTitleQuickPermissions( $instance ) {
+
+ $handler = 'TitleQuickPermissions';
+
+ $title = $this->title;
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $action = '';
+ $errors = [];
+ $rigor = '';
+ $short = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $title, $user, $action, &$errors, $rigor, $short ]
+ );
+
+ return $handler;
+ }
+
+ public function callOutputPageCheckLastModified( $instance ) {
+
+ $handler = 'OutputPageCheckLastModified';
+ $modifiedTimes = [];
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$modifiedTimes ]
+ );
+
+ return $handler;
+ }
+
+ public function callIsFileCacheable( $instance ) {
+
+ $handler = 'IsFileCacheable';
+
+ $article = $this->getMockBuilder( '\Article' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $article->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$article ]
+ );
+
+ return $handler;
+ }
+
+ public function callRejectParserCacheValue( $instance ) {
+
+ $handler = 'RejectParserCacheValue';
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $value = '';
+ $popts = '';
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $value, $wikiPage, $popts ]
+ );
+
+ return $handler;
+ }
+
+ public function callSoftwareInfo( $instance ) {
+
+ $handler = 'SoftwareInfo';
+
+ $software = [];
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$software ]
+ );
+
+ return $handler;
+ }
+
+ public function callBlockIpComplete( $instance ) {
+
+ $handler = 'BlockIpComplete';
+
+ $block = $this->getMockBuilder( '\Block' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $block->expects( $this->any() )
+ ->method( 'getTarget' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $performer = '';
+ $priorBlock = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $block, $performer, $priorBlock ]
+ );
+
+ return $handler;
+ }
+
+ public function callUnblockUserComplete( $instance ) {
+
+ $handler = 'UnblockUserComplete';
+
+ $block = $this->getMockBuilder( '\Block' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $block->expects( $this->any() )
+ ->method( 'getTarget' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $performer = '';
+ $priorBlock = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $block, $performer, $priorBlock ]
+ );
+
+ return $handler;
+ }
+
+ public function callUserGroupsChanged( $instance ) {
+
+ $handler = 'UserGroupsChanged';
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->any() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $user ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWStoreDropTables( $instance ) {
+
+ $handler = 'SMW::Store::dropTables';
+
+ $verbose = false;
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $verbose ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWSQLStoreEntityReferenceCleanUpComplete( $instance ) {
+
+ $handler = 'SMW::SQLStore::EntityReferenceCleanUpComplete';
+
+ if ( !$instance->getHandlerFor( $handler ) ) {
+ return $this->markTestSkipped( "$handler not used" );
+ }
+
+ $id = 42;
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+ $isRedirect = false;
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $this->store, $id, $subject, $isRedirect ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWAdminTaskHandlerFactory( $instance ) {
+
+ $handler = 'SMW::Admin::TaskHandlerFactory';
+
+ if ( !$instance->getHandlerFor( $handler ) ) {
+ return $this->markTestSkipped( "$handler not used" );
+ }
+
+ $taskHandlers = [];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user = $this->getMockBuilder( 'User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ &$taskHandlers, $store, $outputFormatter, $user ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWSQLStorAfterDataUpdateComplete( $instance ) {
+
+ $handler = 'SMW::SQLStore::AfterDataUpdateComplete';
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getOrderedDiffByTable' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getFixedPropertyRecords' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $store, $semanticData, $changeOp ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWStoreBeforeQueryResultLookupComplete( $instance ) {
+
+ $handler = 'SMW::Store::BeforeQueryResultLookupComplete';
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryEngine = $this->getMockBuilder( '\SMW\QueryEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $this->store, $query, &$result, $queryEngine ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWStoreAfterQueryResultLookupComplete( $instance ) {
+
+ $handler = 'SMW::Store::AfterQueryResultLookupComplete';
+
+ $idTableLookup = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'warmUpCache' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'getPropertyValues' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTableLookup ) );
+
+ $result = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $store, &$result ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWBrowseAfterIncomingPropertiesLookupComplete( $instance ) {
+
+ $handler = 'SMW::Browse::AfterIncomingPropertiesLookupComplete';
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists', 'getId' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'getPropertyValues' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $requestOptions = $this->getMockBuilder( '\SMW\RequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $requestOptions->expects( $this->any() )
+ ->method( 'getExtraConditions' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $store, $semanticData, $requestOptions ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWBrowseBeforeIncomingPropertyValuesFurtherLinkCreate( $instance ) {
+
+ $handler = 'SMW::Browse::BeforeIncomingPropertyValuesFurtherLinkCreate';
+
+ $html = '';
+ $property = new DIProperty( 'Foo' );
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $property, $subject, &$html, $this->store ]
+ );
+
+ return $handler;
+ }
+
+ public function callSMWSQLStoreInstallerAfterCreateTablesComplete( $instance ) {
+
+ $handler = 'SMW::SQLStore::Installer::AfterCreateTablesComplete';
+
+ $result = '';
+
+ $this->assertTrue(
+ $instance->isRegistered( $handler )
+ );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageReporter = $this->getMockBuilder( '\Onoi\MessageReporter\MessageReporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $options = $this->getMockBuilder( '\SMW\Options' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertThatHookIsExcutable(
+ $instance->getHandlerFor( $handler ),
+ [ $tableBuilder, $messageReporter, $options ]
+ );
+
+ return $handler;
+ }
+
+ private function assertThatHookIsExcutable( callable $handler, $arguments ) {
+ $this->assertInternalType(
+ 'boolean',
+ call_user_func_array( $handler, $arguments )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/InternalParseBeforeLinksTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/InternalParseBeforeLinksTest.php
new file mode 100644
index 00000000..7665b5ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/InternalParseBeforeLinksTest.php
@@ -0,0 +1,459 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Hooks\InternalParseBeforeLinks;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockTitle;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\InternalParseBeforeLinks
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class InternalParseBeforeLinksTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $parserFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ $this->parserFactory = $this->testEnvironment->getUtilityFactory()->newParserFactory();
+
+ $this->stripState = $this->getMockBuilder( '\StripState' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\InternalParseBeforeLinks',
+ new InternalParseBeforeLinks( $parser, $this->stripState )
+ );
+ }
+
+ public function testNonProcessForEmptyText() {
+
+ $text = '';
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->once() )
+ ->method( 'getOptions' );
+
+ $instance = new InternalParseBeforeLinks(
+ $parser,
+ $this->stripState
+ );
+
+ $this->assertTrue(
+ $instance->process( $text )
+ );
+ }
+
+ public function testDisableProcessOfInterfaceMessageOnNonSpecialPage() {
+
+ $text = 'Foo';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( false ) );
+
+ $parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOptions->expects( $this->once() )
+ ->method( 'getInterfaceMessage' )
+ ->will( $this->returnValue( true ) );
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $parserOptions ) );
+
+ $parser->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new InternalParseBeforeLinks(
+ $parser,
+ $this->stripState
+ );
+
+ $this->assertTrue(
+ $instance->process( $text )
+ );
+ }
+
+ public function testProcessOfInterfaceMessageOnEnabledSpecialPage() {
+
+ $text = 'Foo';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( __METHOD__ ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecial' )
+ ->with( $this->equalTo( 'Bar' ) )
+ ->will( $this->returnValue( true ) );
+
+ $parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOptions->expects( $this->once() )
+ ->method( 'getInterfaceMessage' )
+ ->will( $this->returnValue( true ) );
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $parserOptions ) );
+
+ $instance = new InternalParseBeforeLinks(
+ $parser,
+ $this->stripState
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgEnabledSpecialPage' => [ 'Bar' ]
+ ]
+ );
+
+ $instance->process( $text );
+ }
+
+ public function testProcessOfInterfaceMessageOnSpecialPageWithOnOffMarker() {
+
+ $text = '[[SMW::off]]Foo[[SMW::on]]';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( __METHOD__ ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecial' )
+ ->with( $this->equalTo( 'Bar' ) )
+ ->will( $this->returnValue( true ) );
+
+ $parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $parser->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new InternalParseBeforeLinks(
+ $parser,
+ $this->stripState
+ );
+
+ $instance->process( $text );
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testProcess( $title ) {
+
+ $text = 'Foo';
+ $parser = $this->parserFactory->newFromTitle( $title );
+
+ $instance = new InternalParseBeforeLinks(
+ $parser,
+ $this->stripState
+ );
+
+ $this->assertTrue(
+ $instance->process( $text )
+ );
+ }
+
+ /**
+ * @dataProvider textDataProvider
+ */
+ public function testTextChangeWithParserOuputUpdateIntegration( $parameters, $expected ) {
+
+ $this->testEnvironment->withConfiguration(
+ $parameters['settings']
+ );
+
+ $text = $parameters['text'];
+ $parser = $this->parserFactory->newFromTitle( $parameters['title'] );
+
+ $instance = new InternalParseBeforeLinks(
+ $parser,
+ $this->stripState
+ );
+
+ $smwgEnabledSpecialPage = isset( $parameters['settings']['smwgEnabledSpecialPage'] ) ? $parameters['settings']['smwgEnabledSpecialPage'] : [];
+
+ $instance->setOptions(
+ [
+ 'smwgEnabledSpecialPage' => $smwgEnabledSpecialPage
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->process( $text )
+ );
+
+ $this->assertEquals(
+ $expected['resultText'],
+ $text
+ );
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ $parser->getTitle(),
+ $parser->getOutput()
+ );
+
+ $this->assertEquals(
+ $expected['propertyCount'] > 0,
+ $parserData->hasSemanticData( $parser->getOutput() )
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function titleProvider() {
+
+ #0
+ $provider[] = [ Title::newFromText( __METHOD__ ) ];
+
+ $title = MockTitle::buildMockForMainNamespace();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ #1
+ $provider[] = [ $title ];
+
+ $title = MockTitle::buildMockForMainNamespace();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+
+ #2
+ $provider[] = [ $title ];
+
+ $title = MockTitle::buildMockForMainNamespace();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ #3
+ $provider[] = [ $title ];
+
+ return $provider;
+ }
+
+ public function textDataProvider() {
+
+ $provider = [];
+
+ // #0 NS_MAIN; [[FooBar...]] with a different caption
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'settings' => [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_STRICT
+ ],
+ 'text' => 'Lorem ipsum dolor sit &$% [[FooBar::dictumst|寒ã„]]' .
+ ' [[Bar::tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[foo::9001]] et Donec.',
+ ],
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% [[:Dictumst|寒ã„]]' .
+ ' [[:Tincidunt semper|tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[:9001|9001]] et Donec.',
+ 'propertyCount' => 3,
+ 'propertyLabels' => [ 'Foo', 'Bar', 'FooBar' ],
+ 'propertyValues' => [ 'Dictumst', 'Tincidunt semper', '9001' ]
+ ]
+ ];
+
+ // #1
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'settings' => [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_STRICT
+ ],
+ 'text' => '#REDIRECT [[Foo]]',
+ ],
+ [
+ 'resultText' => '#REDIRECT [[Foo]]',
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_REDI' ],
+ 'propertyValues' => [ 'Foo' ]
+ ]
+ ];
+
+ // #2 NS_SPECIAL, processed but no annotations
+ $title = Title::newFromText( 'Ask', NS_SPECIAL );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'settings' => [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_STRICT,
+ 'smwgEnabledSpecialPage' => [ 'Ask', 'Foo' ]
+ ],
+ 'text' => 'Lorem ipsum dolor sit &$% [[FooBar::dictumst|寒ã„]]' .
+ ' [[Bar::tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[foo::9001]] et Donec.',
+ ],
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% [[:Dictumst|寒ã„]]' .
+ ' [[:Tincidunt semper|tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[:9001|9001]] et Donec.',
+ 'propertyCount' => 0
+ ]
+ ];
+
+ // #3 NS_SPECIAL, not processed, Title::isSpecial returns false
+ $title = Title::newFromText( 'Foo', NS_SPECIAL );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'settings' => [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_STRICT,
+ 'smwgEnabledSpecialPage' => [ 'Ask', 'Foo' ]
+ ],
+ 'text' => 'Lorem ipsum dolor sit &$% [[FooBar::dictumst|寒ã„]]' .
+ ' [[Bar::tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[foo::9001]] et Donec.',
+ ],
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% [[FooBar::dictumst|寒ã„]]' .
+ ' [[Bar::tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[foo::9001]] et Donec.',
+ 'propertyCount' => 0
+ ]
+ ];
+
+ // #4 NS_SPECIAL, not processed, invalid smwgEnabledSpecialPage setting
+ $title = Title::newFromText( 'Foobar', NS_SPECIAL );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'settings' => [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_STRICT,
+ 'smwgEnabledSpecialPage' => []
+ ],
+ 'text' => 'Lorem ipsum dolor sit &$% [[FooBar::dictumst|寒ã„]]' .
+ ' [[Bar::tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[foo::9001]] et Donec.',
+ ],
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% [[FooBar::dictumst|寒ã„]]' .
+ ' [[Bar::tincidunt semper]] facilisi {{volutpat}} Ut quis' .
+ ' [[foo::9001]] et Donec.',
+ 'propertyCount' => 0
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/LinksUpdateConstructedTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/LinksUpdateConstructedTest.php
new file mode 100644
index 00000000..3e1e749a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/LinksUpdateConstructedTest.php
@@ -0,0 +1,238 @@
+<?php
+
+namespace SMW\Test\MediaWiki\Hooks;
+
+use LinksUpdate;
+use ParserOutput;
+use SMW\MediaWiki\Hooks\LinksUpdateConstructed;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\LinksUpdateConstructed
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class LinksUpdateConstructedTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $namespaceExaminer;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ LinksUpdateConstructed::class,
+ new LinksUpdateConstructed( $this->namespaceExaminer )
+ );
+ }
+
+ public function testProcess() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 11001 ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( __METHOD__ ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getPrefixedText' )
+ ->will( $this->returnValue( __METHOD__ ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( false ) );
+
+ $parserOutput = new ParserOutput();
+ $parserOutput->setTitleText( $title->getPrefixedText() );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $idTable->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'clearData', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'clearData' );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new LinksUpdateConstructed(
+ $this->namespaceExaminer
+ );
+
+ $instance->setLogger( $this->testEnvironment->newSpyLogger() );
+ $instance->disableDeferredUpdate();
+
+ $this->assertTrue(
+ $instance->process( new LinksUpdate( $title, $parserOutput ) )
+ );
+ }
+
+ public function testNoExtraParsingForNotEnabledNamespace() {
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgNamespacesWithSemanticLinks',
+ [ NS_HELP => false ]
+ );
+
+ $title = Title::newFromText( __METHOD__, NS_HELP );
+ $parserOutput = new ParserOutput();
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserData->expects( $this->never() )
+ ->method( 'getSemanticData' );
+
+ $parserData->expects( $this->once() )
+ ->method( 'updateStore' );
+
+ $this->testEnvironment->registerObject( 'ParserData', $parserData );
+
+ $linksUpdate = $this->getMockBuilder( '\LinksUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $linksUpdate->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $linksUpdate->expects( $this->atLeastOnce() )
+ ->method( 'getParserOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $instance = new LinksUpdateConstructed(
+ $this->namespaceExaminer
+ );
+
+ $this->assertTrue(
+ $instance->process( $linksUpdate )
+ );
+ }
+
+ public function testTemplateUpdate() {
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgNamespacesWithSemanticLinks',
+ [ NS_HELP => false ]
+ );
+
+ $title = Title::newFromText( __METHOD__, NS_HELP );
+ $parserOutput = new ParserOutput();
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSemanticData', 'updateStore', 'markUpdate' ] )
+ ->getMock();
+
+ $parserData->expects( $this->never() )
+ ->method( 'getSemanticData' );
+
+ $parserData->expects( $this->once() )
+ ->method( 'updateStore' );
+
+ $this->testEnvironment->registerObject( 'ParserData', $parserData );
+
+ $linksUpdate = $this->getMockBuilder( '\LinksUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $linksUpdate->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $linksUpdate->expects( $this->atLeastOnce() )
+ ->method( 'getParserOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $linksUpdate->mTemplates = [ 'Foo' ];
+ $linksUpdate->mRecursive = false;
+
+ $instance = new LinksUpdateConstructed(
+ $this->namespaceExaminer
+ );
+
+ $instance->process( $linksUpdate );
+
+ $this->assertTrue(
+ $parserData->getOption( $parserData::OPT_FORCED_UPDATE )
+ );
+ }
+
+ public function testIsReadOnly_DoNothing() {
+
+ $linksUpdate = $this->getMockBuilder( '\LinksUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $linksUpdate->expects( $this->never() )
+ ->method( 'getTitle' );
+
+ $instance = new LinksUpdateConstructed(
+ $this->namespaceExaminer
+ );
+
+ $instance->isReadOnly( true );
+
+ $this->assertFalse(
+ $instance->process( $linksUpdate )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/NewRevisionFromEditCompleteTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/NewRevisionFromEditCompleteTest.php
new file mode 100644
index 00000000..7e1a89c9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/NewRevisionFromEditCompleteTest.php
@@ -0,0 +1,214 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use ParserOutput;
+use Revision;
+use SMW\DIProperty;
+use SMW\MediaWiki\Hooks\NewRevisionFromEditComplete;
+use SMW\Tests\TestEnvironment;
+use Title;
+use WikiPage;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\NewRevisionFromEditComplete
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class NewRevisionFromEditCompleteTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\PageInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ NewRevisionFromEditComplete::class,
+ new NewRevisionFromEditComplete( $title, $editInfoProvider, $pageInfoProvider )
+ );
+ }
+
+ /**
+ * @dataProvider wikiPageDataProvider
+ */
+ public function testProcess( $settings, $title, $editInfoProvider, $pageInfoProvider, $expected ) {
+
+ $this->testEnvironment->withConfiguration( $settings );
+
+ $instance = new NewRevisionFromEditComplete(
+ $title,
+ $editInfoProvider,
+ $pageInfoProvider
+ );
+
+ $this->assertTrue(
+ $instance->process()
+ );
+
+ if ( $expected ) {
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $editInfoProvider->fetchSemanticData()
+ );
+ }
+ }
+
+ public function wikiPageDataProvider() {
+
+ #0 No parserOutput object
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getOutput' ] )
+ ->getMock();
+
+ $pageInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\PageInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ [],
+ $title,
+ $editInfoProvider,
+ $pageInfoProvider,
+ false
+ ];
+
+ #1 With annotation
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getOutput' ] )
+ ->getMock();
+
+ $editInfoProvider->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( new ParserOutput() ) );
+
+ $pageInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\PageInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageInfoProvider->expects( $this->atLeastOnce() )
+ ->method( 'getModificationDate' )
+ ->will( $this->returnValue( 1272508903 ) );
+
+ $provider[] = [
+ [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MODIFICATION_DATE ],
+ 'smwgDVFeatures' => ''
+ ],
+ $title,
+ $editInfoProvider,
+ $pageInfoProvider,
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_MDAT',
+ 'propertyValues' => [ '2010-04-29T02:41:43' ],
+ ]
+ ];
+
+ #2 on schema page
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo_schema' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_SCHEMA ) );
+
+ $editInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\EditInfoProvider' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getOutput' ] )
+ ->getMock();
+
+ $editInfoProvider->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( new ParserOutput() ) );
+
+ $pageInfoProvider = $this->getMockBuilder( '\SMW\MediaWiki\PageInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $data = json_encode(
+ [ 'description' => 'Foobar', 'type' => 'FOO_ROLE' ]
+ );
+
+ $pageInfoProvider->expects( $this->atLeastOnce() )
+ ->method( 'getNativeData' )
+ ->will( $this->returnValue( $data ) );
+
+ $provider[] =[
+ [
+ 'smwgPageSpecialProperties' => [],
+ 'smwgDVFeatures' => '',
+ 'smwgSchemaTypes' => [ 'FOO_ROLE' => [] ]
+ ],
+ $title,
+ $editInfoProvider,
+ $pageInfoProvider,
+ [
+ 'propertyCount' => 3,
+ 'propertyKeys' => [ '_SCHEMA_DESC', '_SCHEMA_TYPE', '_SCHEMA_DEF' ],
+ 'propertyValues' => [ 'Foobar', 'FOO_ROLE', '{"description":"Foobar","type":"FOO_ROLE"}' ],
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/OutputPageParserOutputTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/OutputPageParserOutputTest.php
new file mode 100644
index 00000000..7f34cfc3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/OutputPageParserOutputTest.php
@@ -0,0 +1,360 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use Language;
+use ParserOutput;
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Hooks\OutputPageParserOutput;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockTitle;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\OutputPageParserOutput
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class OutputPageParserOutputTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $this->testEnvironment->withConfiguration(
+ [
+ 'smwgShowFactbox' => SMW_FACTBOX_NONEMPTY,
+ 'smwgFactboxUseCache' => true,
+ 'smwgMainCacheType' => 'hash'
+ ]
+ );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\OutputPageParserOutput',
+ new OutputPageParserOutput( $outputPage, $parserOutput )
+ );
+ }
+
+ /**
+ * @dataProvider outputDataProvider
+ */
+ public function testProcess( $parameters, $expected ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgNamespacesWithSemanticLinks',
+ $parameters['smwgNamespacesWithSemanticLinks']
+ );
+
+ $outputPage = $parameters['outputPage'];
+ $parserOutput = $parameters['parserOutput'];
+
+ $instance = new OutputPageParserOutput( $outputPage, $parserOutput );
+
+ $cachedFactbox = $this->applicationFactory->create( 'FactboxFactory' )->newCachedFactbox();
+
+ $factboxFactory = $this->getMockBuilder( '\SMW\Factbox\FactboxFactory' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'newCachedFactbox' ] )
+ ->getMock();
+
+ $factboxFactory->expects( $this->any() )
+ ->method( 'newCachedFactbox' )
+ ->will( $this->returnValue( $cachedFactbox ) );
+
+ $this->applicationFactory->registerObject( 'FactboxFactory', $factboxFactory );
+
+ $this->assertEmpty(
+ $cachedFactbox->retrieveContent( $outputPage )
+ );
+
+ $instance->process();
+
+ if ( $expected['text'] == '' ) {
+ return $this->assertFalse( isset( $outputPage->mSMWFactboxText ) );
+ }
+
+ // For expected content continue to verify that the outputPage was amended and
+ // that the content is also available via the CacheStore
+ $text = $outputPage->mSMWFactboxText;
+
+ $this->assertContains( $expected['text'], $text );
+
+ $this->assertEquals(
+ $text,
+ $cachedFactbox->retrieveContent( $outputPage ),
+ 'Asserts that retrieveContent() returns an expected text'
+ );
+
+ // Deliberately clear the outputPage Property to retrieve
+ // content from the CacheStore
+ unset( $outputPage->mSMWFactboxText );
+
+ $this->assertEquals(
+ $text,
+ $cachedFactbox->retrieveContent( $outputPage ),
+ 'Asserts that retrieveContent() is returning text from cache'
+ );
+ }
+
+ public function outputDataProvider() {
+
+ $language = Language::factory( 'en' );
+
+ $title = MockTitle::buildMockForMainNamespace( __METHOD__ . 'mock-subject' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $subject = DIWikiPage::newFromTitle( $title );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'hasVisibleProperties' )
+ ->will( $this->returnValue( true ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromTitle( $title ) ] ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [ new DIProperty( __METHOD__ . 'property' ) ] ) );
+
+ #0 Simple factbox build, returning content
+ $title = MockTitle::buildMock( __METHOD__ . 'title-with-content' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 9098 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'outputPage' => $outputPage,
+ 'parserOutput' => $this->makeParserOutput( $semanticData ),
+ ],
+ [
+ 'text' => $subject->getDBKey()
+ ]
+ ];
+
+ #1 Disabled namespace, no return value expected
+ $title = MockTitle::buildMock( __METHOD__ . 'title-ns-disabled' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 90000 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => false ],
+ 'outputPage' => $outputPage,
+ 'parserOutput' => $this->makeParserOutput( $semanticData ),
+ ],
+ [
+ 'text' => ''
+ ]
+ ];
+
+ // #2 Specialpage, no return value expected
+ $title = MockTitle::buildMock( __METHOD__ . 'mock-specialpage' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'outputPage' => $outputPage,
+ 'parserOutput' => $this->makeParserOutput( $semanticData ),
+ ],
+ [
+ 'text' => ''
+ ]
+ ];
+
+ // #3 Redirect, no return value expected
+ $title = MockTitle::buildMock( __METHOD__ . 'mock-redirect' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( true ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'outputPage' => $outputPage,
+ 'parserOutput' => $this->makeParserOutput( $semanticData ),
+ ],
+ [
+ 'text' => ''
+ ]
+ ];
+
+ // #4 Oldid
+ $title = MockTitle::buildMockForMainNamespace( __METHOD__ . 'mock-oldid' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $context = new \RequestContext( );
+ $context->setRequest( new \FauxRequest( [ 'oldid' => 9001 ], true ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $context ) );
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $provider[] = [
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'outputPage' => $outputPage,
+ 'parserOutput' => $this->makeParserOutput( $semanticData ),
+ ],
+ [
+ 'text' => $subject->getDBKey()
+ ]
+ ];
+
+ return $provider;
+ }
+
+ protected function makeParserOutput( $data ) {
+
+ $parserOutput = new ParserOutput();
+
+ if ( method_exists( $parserOutput, 'setExtensionData' ) ) {
+ $parserOutput->setExtensionData( 'smwdata', $data );
+ } else {
+ $parserOutput->mSMWData = $data;
+ }
+
+ return $parserOutput;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ParserAfterTidyTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ParserAfterTidyTest.php
new file mode 100644
index 00000000..b4ac0c21
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ParserAfterTidyTest.php
@@ -0,0 +1,412 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\DataItemFactory;
+use SMW\MediaWiki\Hooks\ParserAfterTidy;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockTitle;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ParserAfterTidy
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParserAfterTidyTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $applicationFactory;
+ private $parserFactory;
+ private $spyLogger;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $settings = [
+ 'smwgChangePropagationWatchlist' => [],
+ 'smwgMainCacheType' => 'hash',
+ 'smwgEnableUpdateJobs' => false
+ ];
+
+ $this->testEnvironment = new TestEnvironment( $settings );
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->spyLogger = $this->testEnvironment->getUtilityFactory()->newSpyLogger();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ $this->parserFactory = $this->testEnvironment->getUtilityFactory()->newParserFactory();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\ParserAfterTidy',
+ new ParserAfterTidy( $parser )
+ );
+ }
+
+ public function testIsReadOnly() {
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->never() )
+ ->method( 'getTitle' );
+
+ $instance = new ParserAfterTidy( $parser );
+ $instance->isReadOnly( true );
+
+ $text = '';
+ $instance->process( $text );
+ }
+
+ public function testNotEnabledNamespace() {
+
+ $namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $namespaceExaminer->expects( $this->once() )
+ ->method( 'isSemanticEnabled' )
+ ->will( $this->returnValue( false ) );
+
+ $this->testEnvironment->registerObject( 'NamespaceExaminer', $namespaceExaminer );
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // Using this step to verify that the previous NS check
+ // bailed out.
+ $title->expects( $this->never() )
+ ->method( 'isSpecialPage' );
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new ParserAfterTidy( $parser );
+
+ $text = '';
+ $instance->process( $text );
+ }
+
+ private function newMockCache( $id, $containsStatus, $fetchStatus ) {
+
+ $key = $this->applicationFactory->newCacheFactory()->getPurgeCacheKey( $id );
+
+ $cache = $this->getMockBuilder( 'Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->any() )
+ ->method( 'contains' )
+ ->with( $this->equalTo( $key ) )
+ ->will( $this->returnValue( $containsStatus ) );
+
+ $cache->expects( $this->any() )
+ ->method( 'fetch' )
+ ->with( $this->equalTo( $key ) )
+ ->will( $this->returnValue( $fetchStatus ) );
+
+ return $cache;
+ }
+
+ /**
+ * @dataProvider titleDataProvider
+ */
+ public function testProcess( $parameters ) {
+
+ $this->testEnvironment->registerObject( 'Store', $parameters['store'] );
+
+ $cache = $this->newMockCache(
+ $parameters['title']->getArticleID(),
+ $parameters['cache-contains'],
+ $parameters['cache-fetch']
+ );
+
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+
+ $parser = $this->parserFactory->newFromTitle( $parameters['title'] );
+
+ $parser->getOutput()->setProperty(
+ 'smw-semanticdata-status',
+ $parameters['data-status']
+ );
+
+ $parser->getOutput()->setProperty(
+ 'displaytitle',
+ isset( $parameters['displaytitle'] ) ? $parameters['displaytitle'] : false
+ );
+
+ $text = '';
+
+ $instance = new ParserAfterTidy( $parser );
+
+ $this->assertTrue(
+ $instance->process( $text )
+ );
+ }
+
+ public function testSemanticDataParserOuputUpdateIntegration() {
+
+ $settings = [
+ 'smwgMainCacheType' => 'hash',
+ 'smwgEnableUpdateJobs' => false,
+ 'smwgParserFeatures' => SMW_PARSER_HID_CATS,
+ 'smwgCategoryFeatures' => SMW_CAT_REDIRECT | SMW_CAT_INSTANCE
+ ];
+
+ $this->testEnvironment->withConfiguration( $settings );
+
+ $text = '';
+ $title = Title::newFromText( __METHOD__ );
+
+ $parser = $this->parserFactory->newFromTitle( $title );
+
+ $parser->getOutput()->addCategory( 'Foo', 'Foo' );
+ $parser->getOutput()->addCategory( 'Bar', 'Bar' );
+ $parser->getOutput()->setProperty( 'smw-semanticdata-status', true );
+
+ $instance = new ParserAfterTidy( $parser );
+
+ $this->assertTrue(
+ $instance->process( $text )
+ );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_INST', '_SKEY' ],
+ 'propertyValues' => [ 'Foo', 'Bar', $title->getText() ],
+ ];
+
+ $parserData = $this->applicationFactory->newParserData(
+ $title,
+ $parser->getOutput()
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function titleDataProvider() {
+
+ #0 Runs store update
+ $store = $this->getMockBuilder( 'SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'updateData' );
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'inNamespace' )
+ ->will( $this->returnValue( false ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 5001 ) );
+
+ $provider[] = [
+ [
+ 'store' => $store,
+ 'title' => $title,
+ 'cache-contains' => true,
+ 'cache-fetch' => true,
+ 'data-status' => true
+ ]
+ ];
+
+ #1 No cache entry, no store update
+ $store = $this->getMockBuilder( 'SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->never() )
+ ->method( 'updateData' );
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'inNamespace' )
+ ->will( $this->returnValue( false ) );
+
+ $provider[] = [
+ [
+ 'store' => $store,
+ 'title' => $title,
+ 'cache-contains' => false,
+ 'cache-fetch' => false,
+ 'data-status' => true
+ ]
+ ];
+
+ #2 SpecialPage, no store update
+ $store = $this->getMockBuilder( 'SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->never() )
+ ->method( 'updateData' );
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $provider[] = [
+ [
+ 'store' => $store,
+ 'title' => $title,
+ 'cache-contains' => false,
+ 'cache-fetch' => false,
+ 'data-status' => true
+ ]
+ ];
+
+ #3 NS_FILE, no store update
+ $store = $this->getMockBuilder( 'SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->never() )
+ ->method( 'updateData' );
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->any() )
+ ->method( 'inNamespace' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_FILE ) );
+
+ $provider[] = [
+ [
+ 'store' => $store,
+ 'title' => $title,
+ 'cache-contains' => true,
+ 'cache-fetch' => true,
+ 'data-status' => true
+ ]
+ ];
+
+ #4, 1131, No store update when fetch return FALSE
+ $store = $this->getMockBuilder( 'SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->never() )
+ ->method( 'updateData' );
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'inNamespace' )
+ ->will( $this->returnValue( false ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 5001 ) );
+
+ $provider[] = [
+ [
+ 'store' => $store,
+ 'title' => $title,
+ 'cache-contains' => true,
+ 'cache-fetch' => false,
+ 'data-status' => true
+ ]
+ ];
+
+ #5, 1410 displaytitle
+ $store = $this->getMockBuilder( 'SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $title = MockTitle::buildMock( __METHOD__ );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 5001 ) );
+
+ $provider[] = [
+ [
+ 'store' => $store,
+ 'title' => $title,
+ 'cache-contains' => true,
+ 'cache-fetch' => true,
+ 'data-status' => false,
+ 'displaytitle' => 'Foo'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/PersonalUrlsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/PersonalUrlsTest.php
new file mode 100644
index 00000000..20f59cbe
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/PersonalUrlsTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\PersonalUrls;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\PersonalUrls
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class PersonalUrlsTest extends \PHPUnit_Framework_TestCase {
+
+ private $skinTemplate;
+ private $jobQueue;
+
+ protected function setUp() {
+
+ $this->skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PersonalUrls::class,
+ new PersonalUrls( $this->skinTemplate, $this->jobQueue )
+ );
+ }
+
+ public function testProcessOnJobQueueWatchlist() {
+
+ $output = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->skinTemplate->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $output ) );
+
+ $personalUrls = [];
+
+ $instance = new PersonalUrls(
+ $this->skinTemplate,
+ $this->jobQueue
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgJobQueueWatchlist' => [ 'Foo' ],
+ 'prefs-jobqueue-watchlist' => true
+ ]
+ );
+
+ $instance->process( $personalUrls );
+
+ $this->assertArrayHasKey(
+ 'smw-jobqueue-watchlist',
+ $personalUrls
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/RejectParserCacheValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/RejectParserCacheValueTest.php
new file mode 100644
index 00000000..7580a2cb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/RejectParserCacheValueTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Hooks\RejectParserCacheValue;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\RejectParserCacheValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RejectParserCacheValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dependencyLinksUpdateJournal;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->dependencyLinksUpdateJournal = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksUpdateJournal' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ RejectParserCacheValue::class,
+ new RejectParserCacheValue( $this->dependencyLinksUpdateJournal )
+ );
+ }
+
+ public function testProcessOnJournalEntryToReject() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $this->dependencyLinksUpdateJournal->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $this->dependencyLinksUpdateJournal->expects( $this->once() )
+ ->method( 'delete' );
+
+ $instance = new RejectParserCacheValue(
+ $this->dependencyLinksUpdateJournal
+ );
+
+ $this->assertFalse(
+ $instance->process( $subject->getTitle() )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderGetConfigVarsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderGetConfigVarsTest.php
new file mode 100644
index 00000000..41a750ac
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderGetConfigVarsTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\ResourceLoaderGetConfigVars;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ResourceLoaderGetConfigVars
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ResourceLoaderGetConfigVarsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ResourceLoaderGetConfigVars::class,
+ new ResourceLoaderGetConfigVars()
+ );
+ }
+
+ public function testProcess() {
+
+ $vars = [];
+
+ $instance = new ResourceLoaderGetConfigVars();
+ $instance->process( $vars );
+
+ $this->assertArrayHasKey(
+ 'smw-config',
+ $vars
+ );
+
+ $this->assertArrayHasKey(
+ 'namespaces',
+ $vars['smw-config']
+ );
+
+ $this->assertArrayHasKey(
+ 'settings',
+ $vars['smw-config']
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderTestModulesTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderTestModulesTest.php
new file mode 100644
index 00000000..dea78b79
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/ResourceLoaderTestModulesTest.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\ResourceLoaderTestModules;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\ResourceLoaderTestModules
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ResourceLoaderTestModulesTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $resourceLoader = $this->getMockBuilder( '\ResourceLoader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ResourceLoaderTestModules::class,
+ new ResourceLoaderTestModules( $resourceLoader )
+ );
+ }
+
+ public function testProcess() {
+
+ $resourceLoader = $this->getMockBuilder( '\ResourceLoader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $testModules = [];
+
+ $instance = new ResourceLoaderTestModules( $resourceLoader );
+ $instance->process( $testModules );
+
+ $this->assertArrayHasKey(
+ 'ext.smw.tests',
+ $testModules['qunit']
+ );
+
+ $this->assertArrayHasKey(
+ 'localBasePath',
+ $testModules['qunit']['ext.smw.tests']
+ );
+
+ $this->assertArrayHasKey(
+ 'remoteExtPath',
+ $testModules['qunit']['ext.smw.tests']
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinAfterContentTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinAfterContentTest.php
new file mode 100644
index 00000000..eda42991
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinAfterContentTest.php
@@ -0,0 +1,357 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Hooks\SkinAfterContent;
+use SMW\Settings;
+use SMW\Tests\Utils\Mock\MockTitle;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\SkinAfterContent
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SkinAfterContentTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $settings = Settings::newFromArray( [
+ 'smwgFactboxFeatures' => SMW_FACTBOX_CACHE,
+ 'smwgMainCacheType' => 'hash',
+ 'smwgSemanticsEnabled' => true
+ ] );
+
+ $this->applicationFactory->registerObject( 'Settings', $settings );
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\SkinAfterContent',
+ new SkinAfterContent( $skin )
+ );
+ }
+
+ public function testTryToPerformUpdateOnNullSkin() {
+
+ $data = '';
+ $instance = new SkinAfterContent( null );
+
+ $this->assertTrue(
+ $instance->performUpdate( $data )
+ );
+ }
+
+ /**
+ * @dataProvider outputDataProvider
+ */
+ public function testperformUpdateFactboxPresenterIntegration( $parameters, $expected ) {
+
+ $data = '';
+
+ $instance = new SkinAfterContent( $parameters['skin'] );
+
+ // Replace CachedFactbox instance
+ if ( isset( $parameters['title'] ) ) {
+
+ $cachedFactbox = $this->applicationFactory->create( 'FactboxFactory' )->newCachedFactbox();
+
+ $cachedFactbox->addContentToCache(
+ $cachedFactbox->makeCacheKey( $parameters['title'] ),
+ $parameters['text']
+ );
+
+ $factboxFactory = $this->getMockBuilder( '\SMW\Factbox\FactboxFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $factboxFactory->expects( $this->once() )
+ ->method( 'newCachedFactbox' )
+ ->will( $this->returnValue( $cachedFactbox ) );
+
+ $this->applicationFactory->registerObject( 'FactboxFactory', $factboxFactory );
+ }
+
+ $this->assertTrue(
+ $instance->performUpdate( $data )
+ );
+
+ $this->assertEquals(
+ $expected['text'],
+ $data
+ );
+ }
+
+ public function outputDataProvider() {
+
+ $text = __METHOD__ . 'text-0';
+
+ #0 Retrieve content from outputPage property
+ $title = MockTitle::buildMock( __METHOD__ . 'from-property' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 10001 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->mSMWFactboxText = $text;
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( null ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $outputPage ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $provider[] = [
+ [ 'skin' => $skin ],
+ [ 'text' => $text ]
+ ];
+
+ #1 Retrieve content from cache
+ $title = MockTitle::buildMock( __METHOD__ . 'from-cache' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 10002 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $text = __METHOD__ . 'text-1';
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $outputPage ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $provider[] = [
+ [ 'skin' => $skin, 'text' => $text, 'title' => $outputPage->getTitle() ],
+ [ 'text' => $text ]
+ ];
+
+ // #2 Special page
+ $text = __METHOD__ . 'text-2';
+
+ $title = MockTitle::buildMock( __METHOD__ . 'specialpage' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( true ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->mSMWFactboxText = $text;
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $outputPage ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( new \RequestContext() ) );
+
+ $provider[] = [
+ [ 'skin' => $skin, 'text' => $text ],
+ [ 'text' => '' ]
+ ];
+
+ // #3 "edit" request
+ $text = __METHOD__ . 'text-3';
+
+ $title = MockTitle::buildMock( __METHOD__ . 'edit-request' );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( 10003 ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $outputPage->mSMWFactboxText = $text;
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $outputPage ) );
+
+ $context = new \RequestContext( );
+ $context->setRequest( new \FauxRequest( [ 'action' => 'edit' ], true ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $context ) );
+
+ $provider[] = [
+ [ 'skin' => $skin, 'text' => $text ],
+ [ 'text' => $text ]
+ ];
+
+ // #4 "delete" request
+ $text = __METHOD__ . 'text-4';
+
+ $title = MockTitle::buildMock( __METHOD__ . 'delete-request' );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skin->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $outputPage ) );
+
+ $context = new \RequestContext( );
+ $context->setRequest( new \FauxRequest( [ 'action' => 'delete' ], true ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $context ) );
+
+ $provider[] = [
+ [ 'skin' => $skin, 'text' => $text ],
+ [ 'text' => '' ]
+ ];
+
+ // #5 "purge" request
+ $text = __METHOD__ . 'text-purge';
+
+ $title = MockTitle::buildMock( __METHOD__ . 'purge-request' );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skin->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $skin->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $outputPage ) );
+
+ $context = new \RequestContext( );
+ $context->setRequest( new \FauxRequest( [ 'action' => 'purge' ], true ) );
+
+ $skin->expects( $this->atLeastOnce() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $context ) );
+
+ $provider[] = [
+ [ 'skin' => $skin, 'text' => $text ],
+ [ 'text' => '' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinTemplateNavigationTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinTemplateNavigationTest.php
new file mode 100644
index 00000000..f6f9547d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SkinTemplateNavigationTest.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\SkinTemplateNavigation;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\SkinTemplateNavigation
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SkinTemplateNavigationTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $links = [];
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\SkinTemplateNavigation',
+ new SkinTemplateNavigation( $skinTemplate, $links )
+ );
+ }
+
+ public function testProcess() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->atLeastOnce() )
+ ->method( 'isAllowed' )
+ ->will( $this->returnValue( true ) );
+
+ $output = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate = $this->getMockBuilder( '\SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $output ) );
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'msg' )
+ ->will( $this->returnValue( $message ) );
+
+ $skinTemplate->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $links = [];
+
+ $instance = new SkinTemplateNavigation( $skinTemplate, $links );
+ $instance->process();
+
+ $this->assertArrayHasKey( 'purge', $links['actions'] );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialSearchResultsPrependTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialSearchResultsPrependTest.php
new file mode 100644
index 00000000..fa7d4aa3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialSearchResultsPrependTest.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\SpecialSearchResultsPrepend;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\SpecialSearchResultsPrepend
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SpecialSearchResultsPrependTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $specialSearch = $this->getMockBuilder( '\SpecialSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ SpecialSearchResultsPrepend::class,
+ new SpecialSearchResultsPrepend( $specialSearch, $outputPage )
+ );
+ }
+
+ public function testProcess() {
+
+ $search = $this->getMockBuilder( '\SMWSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $specialSearch = $this->getMockBuilder( '\SpecialSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $specialSearch->expects( $this->atLeastOnce() )
+ ->method( 'getSearchEngine' )
+ ->will( $this->returnValue( $search ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' );
+
+ $instance = new SpecialSearchResultsPrepend(
+ $specialSearch,
+ $outputPage
+ );
+
+ $instance->setOptions(
+ [
+ 'prefs-suggester-textinput' => true,
+ 'prefs-disable-search-info' => null
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->process( '' )
+ );
+ }
+
+ public function testProcess_DisabledInfo() {
+
+ $search = $this->getMockBuilder( '\SMWSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $specialSearch = $this->getMockBuilder( '\SpecialSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $specialSearch->expects( $this->atLeastOnce() )
+ ->method( 'getSearchEngine' )
+ ->will( $this->returnValue( $search ) );
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->never() )
+ ->method( 'addHtml' );
+
+ $instance = new SpecialSearchResultsPrepend(
+ $specialSearch,
+ $outputPage
+ );
+
+ $instance->setOptions(
+ [
+ 'prefs-suggester-textinput' => true,
+ 'prefs-disable-search-info' => true
+ ]
+ );
+
+ $instance->process( '' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialStatsAddExtraTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialStatsAddExtraTest.php
new file mode 100644
index 00000000..f2ae87bb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/SpecialStatsAddExtraTest.php
@@ -0,0 +1,164 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Hooks\SpecialStatsAddExtra;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\SpecialStatsAddExtra
+ * @group smenatic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SpecialStatsAddExtraTest extends \PHPUnit_Framework_TestCase {
+
+ protected function tearDown() {
+ ApplicationFactory::clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ SpecialStatsAddExtra::class,
+ new SpecialStatsAddExtra( $store )
+ );
+ }
+
+ /**
+ * @dataProvider statisticsDataProvider
+ */
+ public function testProcess( $setup, $expected ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getStatistics' )
+ ->will( $this->returnValue( $setup['statistics'] ) );
+
+ $extraStats = $setup['extraStats'];
+
+ $instance = new SpecialStatsAddExtra( $store );
+
+ $instance->setOptions(
+ [
+ 'smwgSemanticsEnabled' => true
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->process( $extraStats )
+ );
+
+ $this->assertTrue(
+ $this->matchArray( $extraStats, $expected['statistics'] )
+ );
+ }
+
+ public function testProcessOnSQLStore() {
+
+ $extraStats = [];
+
+ $instance = new SpecialStatsAddExtra(
+ ApplicationFactory::getInstance()->getStore()
+ );
+
+ $instance->setOptions(
+ [
+ 'smwgSemanticsEnabled' => true
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->process( $extraStats )
+ );
+
+ // This is a "cheap" check against the SQLStore as it could return any
+ // value therefore we use a message key as only known constant to verify
+ // that the matching process was successful
+ $this->assertTrue(
+ $this->matchArray( $extraStats, 'smw-statistics-property-instance' )
+ );
+ }
+
+ public function matchArray( array $matcher, $searchValue ) {
+
+ foreach ( $matcher as $key => $value ) {
+
+ if ( $searchValue === $key || $searchValue === $value ) {
+ return true;
+ };
+
+ if ( is_array( $value ) ) {
+ return $this->matchArray( $value, $searchValue );
+ };
+ }
+
+ return $searchValue !== null ? false : true;
+ }
+
+ public function statisticsDataProvider() {
+
+ $input = [
+ 'PROPUSES' => 1001
+ ];
+
+ #0
+ $provider[] = [
+ [
+ 'extraStats' => [],
+ 'statistics' => $input
+ ],
+ [
+ 'statistics' => 1001
+ ]
+ ];
+
+ #1 unknown
+ $provider[] = [
+ [
+ 'extraStats' => [],
+ 'statistics' => [ 'Yeey' => 2002 ]
+ ],
+ [
+ 'statistics' => null
+ ]
+ ];
+
+ #2 MW 1.21+
+ $provider[] = [
+ [
+ 'extraStats' => [],
+ 'statistics' => $input
+ ],
+ [
+ 'statistics' => 1001
+ ]
+ ];
+
+ #3 MW 1.21+ - unknown
+ $provider[] = [
+ [
+ 'extraStats' => [],
+ 'statistics' => [ 'Quuxy' => 2002 ]
+ ],
+ [
+ 'statistics' => null
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsAlwaysKnownTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsAlwaysKnownTest.php
new file mode 100644
index 00000000..d3169d50
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsAlwaysKnownTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\TitleIsAlwaysKnown;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\TitleIsAlwaysKnown
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class TitleIsAlwaysKnownTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = '';
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\TitleIsAlwaysKnown',
+ new TitleIsAlwaysKnown( $title, $result )
+ );
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testPerformUpdate( $namespace, $text, $expected ) {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( $namespace ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( $text ) );
+
+ $result = '';
+
+ $instance = new TitleIsAlwaysKnown( $title, $result );
+ $this->assertTrue( $instance->process() );
+
+ $this->assertEquals( $expected, $result );
+ }
+
+ public function titleProvider() {
+
+ $provider = [
+ [ SMW_NS_PROPERTY, 'Modification date', true ],
+ [ SMW_NS_PROPERTY, 'Foo', false ],
+ [ NS_MAIN, 'Modification date', false ],
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsMovableTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsMovableTest.php
new file mode 100644
index 00000000..136b094d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleIsMovableTest.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\TitleIsMovable;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\TitleIsMovable
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class TitleIsMovableTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\TitleIsMovable',
+ new TitleIsMovable( $title )
+ );
+ }
+
+ public function testPredefinedPropertyPageIsNotMovable() {
+
+ $title = Title::newFromText( 'Modification date', SMW_NS_PROPERTY );
+ $isMovable = true;
+
+ $instance = new TitleIsMovable( $title );
+
+ $this->assertTrue(
+ $instance->process( $isMovable )
+ );
+
+ $this->assertFalse(
+ $isMovable
+ );
+ }
+
+ public function testUserdefinedPropertyPageIsMovable() {
+
+ $title = Title::newFromText( 'Foo', SMW_NS_PROPERTY );
+ $isMovable = true;
+
+ $instance = new TitleIsMovable( $title );
+
+ $this->assertTrue(
+ $instance->process( $isMovable )
+ );
+
+ $this->assertTrue(
+ $isMovable
+ );
+ }
+
+ public function testNonPropertyPageIsAlwaysMovable() {
+
+ $title = Title::newFromText( 'Foo', NS_MAIN );
+ $isMovable = true;
+
+ $instance = new TitleIsMovable( $title );
+
+ $this->assertTrue(
+ $instance->process( $isMovable )
+ );
+
+ $this->assertTrue(
+ $isMovable
+ );
+ }
+
+ public function testRulePageIsAlwaysNotMovable() {
+
+ $title = Title::newFromText( 'Foo', SMW_NS_SCHEMA );
+ $isMovable = true;
+
+ $instance = new TitleIsMovable( $title );
+
+ $this->assertTrue(
+ $instance->process( $isMovable )
+ );
+
+ $this->assertFalse(
+ $isMovable
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleMoveCompleteTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleMoveCompleteTest.php
new file mode 100644
index 00000000..9a60ba3e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/TitleMoveCompleteTest.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\TitleMoveComplete;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use SMW\Tests\Utils\Mock\MockTitle;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\TitleMoveComplete
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class TitleMoveCompleteTest extends \PHPUnit_Framework_TestCase {
+
+ private $user;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->user = new MockSuperUser();
+
+ $settings = [
+ 'smwgMainCacheType' => 'hash',
+ 'smwgAutoRefreshOnPageMove' => true,
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true, NS_HELP => false ]
+ ];
+
+ $this->testEnvironment->withConfiguration(
+ $settings
+ );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $oldTitle = MockTitle::buildMock( 'old' );
+ $newTitle = MockTitle::buildMock( 'new' );
+
+ $instance = new TitleMoveComplete(
+ $oldTitle,
+ $newTitle,
+ $this->user,
+ 0,
+ 0
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Hooks\TitleMoveComplete',
+ $instance
+ );
+ }
+
+ public function testChangeSubjectForSupportedSemanticNamespace() {
+
+ $oldTitle = \Title::newFromText( 'Old' );
+ $newTitle = \Title::newFromText( 'New' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->never() )
+ ->method( 'changeTitle' );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new TitleMoveComplete(
+ $oldTitle,
+ $newTitle,
+ $this->user,
+ 0,
+ 0
+ );
+
+ $this->assertTrue(
+ $instance->process()
+ );
+ }
+
+ public function testDeleteSubjectForNotSupportedSemanticNamespace() {
+
+ $oldTitle = \Title::newFromText( 'Old' );
+ $newTitle = \Title::newFromText( 'New', NS_HELP );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'deleteSubject' )
+ ->with(
+ $this->equalTo( $oldTitle ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new TitleMoveComplete(
+ $oldTitle,
+ $newTitle,
+ $this->user,
+ 0,
+ 0
+ );
+
+ $this->assertTrue(
+ $instance->process()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/UserChangeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/UserChangeTest.php
new file mode 100644
index 00000000..be037358
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Hooks/UserChangeTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Hooks;
+
+use SMW\MediaWiki\Hooks\UserChange;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Hooks\UserChange
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class UserChangeTest extends \PHPUnit_Framework_TestCase {
+
+ private $namespaceExaminer;
+ private $testEnvironment;
+ private $jobFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobFactory', $this->jobFactory );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ UserChange::class,
+ new UserChange( $this->namespaceExaminer )
+ );
+ }
+
+ public function testOnEnabledUserNamespace() {
+
+ $job = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\UpdateJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->once() )
+ ->method( 'newUpdateJob' )
+ ->will( $this->returnValue( $job ) );
+
+ $this->namespaceExaminer->expects( $this->any() )
+ ->method( 'isSemanticEnabled' )
+ ->with( $this->equalTo( NS_USER ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new UserChange(
+ $this->namespaceExaminer
+ );
+
+ $instance->setOrigin( 'Foo' );
+
+ $this->assertTrue(
+ $instance->process( 'Foo' )
+ );
+ }
+
+ public function testOnEnabledUserNamespace_User() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $job = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\UpdateJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->once() )
+ ->method( 'newUpdateJob' )
+ ->will( $this->returnValue( $job ) );
+
+ $this->namespaceExaminer->expects( $this->any() )
+ ->method( 'isSemanticEnabled' )
+ ->with( $this->equalTo( NS_USER ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new UserChange(
+ $this->namespaceExaminer
+ );
+
+ $instance->setOrigin( 'Foo' );
+
+ $this->assertTrue(
+ $instance->process( $user )
+ );
+ }
+
+ public function testOnDisabledUserNamespace() {
+
+ $this->jobFactory->expects( $this->never() )
+ ->method( 'newUpdateJob' );
+
+ $this->namespaceExaminer->expects( $this->any() )
+ ->method( 'isSemanticEnabled' )
+ ->with( $this->equalTo( NS_USER ) )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new UserChange(
+ $this->namespaceExaminer
+ );
+
+ $this->assertFalse(
+ $instance->process( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobFactoryTest.php
new file mode 100644
index 00000000..3ae94077
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobFactoryTest.php
@@ -0,0 +1,179 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\JobFactory;
+use Title;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\JobFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class JobFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ JobFactory::class,
+ new JobFactory()
+ );
+ }
+
+ /**
+ * @dataProvider typeProvider
+ */
+ public function testNewByType( $type, $expected ) {
+
+ $instance = new JobFactory();
+
+ $this->assertInstanceOf(
+ $expected,
+ $instance->newByType( $type, Title::newFromText( __METHOD__ ) )
+ );
+ }
+
+ /**
+ * @dataProvider typeProvider
+ */
+ public function testNewByTypeWithNullTitle( $type ) {
+
+ $instance = new JobFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Jobs\NullJob',
+ $instance->newByType( $type, null )
+ );
+ }
+
+ public function testNewByTypeOnUnknownJobThrowsException() {
+
+ $instance = new JobFactory();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->newByType( 'Foo', Title::newFromText( __METHOD__ ) );
+ }
+
+ public function typeProvider() {
+
+ $provider[] = [
+ 'SMW\RefreshJob',
+ '\SMW\MediaWiki\Jobs\RefreshJob'
+ ];
+
+ $provider[] = [
+ 'smw.refresh',
+ '\SMW\MediaWiki\Jobs\RefreshJob'
+ ];
+
+ $provider[] = [
+ 'SMW\UpdateJob',
+ '\SMW\MediaWiki\Jobs\UpdateJob'
+ ];
+
+ $provider[] = [
+ 'smw.update',
+ '\SMW\MediaWiki\Jobs\UpdateJob'
+ ];
+
+ $provider[] = [
+ 'SMW\UpdateDispatcherJob',
+ '\SMW\MediaWiki\Jobs\UpdateDispatcherJob'
+ ];
+
+ $provider[] = [
+ 'smw.updateDispatcher',
+ '\SMW\MediaWiki\Jobs\UpdateDispatcherJob'
+ ];
+
+ $provider[] = [
+ 'SMW\ParserCachePurgeJob',
+ '\SMW\MediaWiki\Jobs\ParserCachePurgeJob'
+ ];
+
+ $provider[] = [
+ 'smw.parserCachePurge',
+ '\SMW\MediaWiki\Jobs\ParserCachePurgeJob'
+ ];
+
+ $provider[] = [
+ 'SMW\FulltextSearchTableUpdateJob',
+ '\SMW\MediaWiki\Jobs\FulltextSearchTableUpdateJob'
+ ];
+
+ $provider[] = [
+ 'smw.fulltextSearchTableUpdate',
+ '\SMW\MediaWiki\Jobs\FulltextSearchTableUpdateJob'
+ ];
+
+ $provider[] = [
+ 'SMW\EntityIdDisposerJob',
+ '\SMW\MediaWiki\Jobs\EntityIdDisposerJob'
+ ];
+
+ $provider[] = [
+ 'smw.entityIdDisposer',
+ '\SMW\MediaWiki\Jobs\EntityIdDisposerJob'
+ ];
+
+ $provider[] = [
+ 'SMW\PropertyStatisticsRebuildJob',
+ '\SMW\MediaWiki\Jobs\PropertyStatisticsRebuildJob'
+ ];
+
+ $provider[] = [
+ 'smw.propertyStatisticsRebuild',
+ '\SMW\MediaWiki\Jobs\PropertyStatisticsRebuildJob'
+ ];
+
+ $provider[] = [
+ 'SMW\FulltextSearchTableRebuildJob',
+ '\SMW\MediaWiki\Jobs\FulltextSearchTableRebuildJob'
+ ];
+
+ $provider[] = [
+ 'smw.fulltextSearchTableRebuild',
+ '\SMW\MediaWiki\Jobs\FulltextSearchTableRebuildJob'
+ ];
+
+ $provider[] = [
+ 'SMW\ChangePropagationDispatchJob',
+ '\SMW\MediaWiki\Jobs\ChangePropagationDispatchJob'
+ ];
+
+ $provider[] = [
+ 'smw.changePropagationDispatch',
+ '\SMW\MediaWiki\Jobs\ChangePropagationDispatchJob'
+ ];
+
+ $provider[] = [
+ 'SMW\ChangePropagationUpdateJob',
+ '\SMW\MediaWiki\Jobs\ChangePropagationUpdateJob'
+ ];
+
+ $provider[] = [
+ 'smw.changePropagationUpdate',
+ '\SMW\MediaWiki\Jobs\ChangePropagationUpdateJob'
+ ];
+
+ $provider[] = [
+ 'SMW\ChangePropagationClassUpdateJob',
+ '\SMW\MediaWiki\Jobs\ChangePropagationClassUpdateJob'
+ ];
+
+ $provider[] = [
+ 'smw.changePropagationClassUpdate',
+ '\SMW\MediaWiki\Jobs\ChangePropagationClassUpdateJob'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobQueueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobQueueTest.php
new file mode 100644
index 00000000..220f1ce6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/JobQueueTest.php
@@ -0,0 +1,244 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\JobQueue;
+
+/**
+ * @covers \SMW\MediaWiki\JobQueue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class JobQueueTest extends \PHPUnit_Framework_TestCase {
+
+ private $jobQueueGroup;
+
+ protected function setup() {
+
+ $this->jobQueueGroup = $this->getMockBuilder( '\JobQueueGroup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ JobQueue::class,
+ new JobQueue( $this->jobQueueGroup )
+ );
+ }
+
+ public function testRunFromQueue() {
+
+ $jobQueue = $this->getMockBuilder( '\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'FakeJob' ) )
+ ->will( $this->returnValue( $jobQueue ) );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+
+ // MediaWiki's JobQueue::pop !!!
+ try {
+ $log = $instance->runFromQueue( [ 'FakeJob' => 2 ] );
+ } catch ( \Exception $e ) {
+ // Do nothing
+ }
+ }
+
+ public function testPop() {
+
+ $jobQueue = $this->getMockBuilder( '\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'FakeJob' ) )
+ ->will( $this->returnValue( $jobQueue ) );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+
+ // MediaWiki's JobQueue::pop !!!
+ try {
+ $instance->pop( 'FakeJob' );
+ } catch ( \Exception $e ) {
+ // Do nothing
+ }
+ }
+
+ public function testAck() {
+
+ $job = $this->getMockBuilder( '\Job' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getType', 'run' ] )
+ ->getMock();
+
+ $job->expects( $this->atLeastOnce() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'FakeJob' ) );
+
+ $jobQueue = $this->getMockBuilder( '\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'FakeJob' ) )
+ ->will( $this->returnValue( $jobQueue ) );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+
+ // MediaWiki's JobQueue::ack !!!
+ try {
+ $instance->ack( $job );
+ } catch ( \Exception $e ) {
+ // Do nothing
+ }
+ }
+
+ public function testDeleteWithDisabledCache() {
+
+ $jobQueue = $this->getMockBuilder( '\JobQueue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'assertNotReadOnly', 'doDelete', 'doFlushCaches' ] )
+ ->getMockForAbstractClass();
+
+ $jobQueue->expects( $this->any() )
+ ->method( 'assertNotReadOnly' )
+ ->will( $this->returnValue( false ) );
+
+ $jobQueue->expects( $this->once() )
+ ->method( 'doDelete' );
+
+ $jobQueue->expects( $this->once() )
+ ->method( 'doFlushCaches' );
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'FakeJob' ) )
+ ->will( $this->returnValue( $jobQueue ) );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+ $instance->disableCache( true );
+
+ $instance->delete( 'FakeJob' );
+ }
+
+ public function testPush() {
+
+ $fakeJob = $this->getMockBuilder( '\Job' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'push' );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+ $instance->push( $fakeJob );
+ }
+
+ public function testLazyPush() {
+
+ if ( !method_exists( $this->jobQueueGroup, 'lazyPush' ) ) {
+ $this->markTestSkipped( 'JobQueueGroup::lazyPush is not supported.' );
+ }
+
+ $fakeJob = $this->getMockBuilder( '\Job' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'lazyPush' );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+ $instance->lazyPush( $fakeJob );
+ }
+
+ public function testGetQueueSizes() {
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'getQueueSizes' );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+ $instance->getQueueSizes();
+ }
+
+ public function testGetQueueSize() {
+
+ $jobQueue = $this->getMockBuilder( '\JobQueue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doGetSize', 'doFlushCaches' ] )
+ ->getMockForAbstractClass();
+
+ $jobQueue->expects( $this->once() )
+ ->method( 'doGetSize' );
+
+ $jobQueue->expects( $this->once() )
+ ->method( 'doFlushCaches' );
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'FakeJob' ) )
+ ->will( $this->returnValue( $jobQueue ) );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+ $instance->disableCache( true );
+
+ $instance->getQueueSize( 'FakeJob' );
+ }
+
+ public function testHasPendingJob() {
+
+ $jobQueue = $this->getMockBuilder( '\JobQueue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doGetSize' ] )
+ ->getMockForAbstractClass();
+
+ $jobQueue->expects( $this->once() )
+ ->method( 'doGetSize' )
+ ->will( $this->returnValue( 1 ) );
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'FakeJob' ) )
+ ->will( $this->returnValue( $jobQueue ) );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+
+ $this->assertTrue(
+ $instance->hasPendingJob( 'FakeJob' )
+ );
+ }
+
+ public function testHasPendingJobWithLegacyName() {
+
+ $jobQueue = $this->getMockBuilder( '\JobQueue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'doGetSize' ] )
+ ->getMockForAbstractClass();
+
+ $jobQueue->expects( $this->once() )
+ ->method( 'doGetSize' )
+ ->will( $this->returnValue( 1 ) );
+
+ $this->jobQueueGroup->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'smw.fake' ) )
+ ->will( $this->returnValue( $jobQueue ) );
+
+ $instance = new JobQueue( $this->jobQueueGroup );
+
+ $this->assertTrue(
+ $instance->hasPendingJob( 'SMW\FakeJob' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationClassUpdateJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationClassUpdateJobTest.php
new file mode 100644
index 00000000..85bfd594
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationClassUpdateJobTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\ChangePropagationClassUpdateJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\ChangePropagationClassUpdateJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangePropagationClassUpdateJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ChangePropagationClassUpdateJob::class,
+ new ChangePropagationClassUpdateJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider jobProvider
+ */
+ public function testRun( $subject, $parameters ) {
+
+ $instance = new ChangePropagationClassUpdateJob(
+ $subject->getTitle(),
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function jobProvider() {
+
+ $provider[] = [
+ DIWikiPage::newFromText( __METHOD__ ),
+ []
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php
new file mode 100644
index 00000000..9609828b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationDispatchJobTest.php
@@ -0,0 +1,229 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\ChangePropagationDispatchJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\ChangePropagationDispatchJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangePropagationDispatchJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ChangePropagationDispatchJob::class,
+ new ChangePropagationDispatchJob( $title )
+ );
+ }
+
+ public function testCleanUp() {
+
+ $subject = DIWikiPage::newFromText(__METHOD__, SMW_NS_PROPERTY );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->getMockForAbstractClass();
+
+ $cache->expects( $this->once() )
+ ->method( 'delete' );
+
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+
+ ChangePropagationDispatchJob::cleanUp( $subject );
+ }
+
+ public function testHasPendingJobs() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->getMockForAbstractClass();
+
+ $cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( 42 ) );
+
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+
+ $this->assertTrue(
+ ChangePropagationDispatchJob::hasPendingJobs( $subject )
+ );
+ }
+
+ public function testGetPendingJobsCount() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->getMockForAbstractClass();
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( 42 ) );
+
+ $this->testEnvironment->registerObject( 'Cache', $cache );
+
+ $this->assertSame(
+ 42,
+ ChangePropagationDispatchJob::getPendingJobsCount( $subject )
+ );
+ }
+
+ public function testFindAndDispatchOnNonPropertyEntity() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueue->expects( $this->never() )
+ ->method( 'lazyPush' );
+
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+
+ $instance = new ChangePropagationDispatchJob(
+ $subject->getTitle()
+ );
+
+ $instance->run();
+ }
+
+ public function testPlanAsJob() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueue->expects( $this->once() )
+ ->method( 'lazyPush' );
+
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+
+ ChangePropagationDispatchJob::planAsJob( $subject );
+ }
+
+ public function testFindAndDispatchOnPropertyEntity() {
+
+ $subject = DIWikiPage::newFromText( 'Foo', SMW_NS_PROPERTY );
+
+ $tempFile = $this->getMockBuilder( '\SMW\Utils\TempFile' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tempFile->expects( $this->atLeastOnce() )
+ ->method( 'write' );
+
+ $this->testEnvironment->registerObject( 'TempFile', $tempFile );
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueue->expects( $this->atLeastOnce() )
+ ->method( 'lazyPush' );
+
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPropertyID' ] )
+ ->getMock();
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher->expects( $this->atLeastOnce() )
+ ->method( 'getDefaultDataItemTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getAllPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new ChangePropagationDispatchJob(
+ $subject->getTitle(),
+ [
+ 'isTypePropagation' => true
+ ]
+ );
+
+ $instance->run();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationUpdateJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationUpdateJobTest.php
new file mode 100644
index 00000000..16ef47e0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ChangePropagationUpdateJobTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\ChangePropagationUpdateJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\ChangePropagationUpdateJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangePropagationUpdateJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ChangePropagationUpdateJob::class,
+ new ChangePropagationUpdateJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider jobProvider
+ */
+ public function testRun( $subject, $parameters ) {
+
+ $instance = new ChangePropagationUpdateJob(
+ $subject->getTitle(),
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function jobProvider() {
+
+ $provider[] = [
+ DIWikiPage::newFromText( __METHOD__ ),
+ []
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/EntityIdDisposerJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/EntityIdDisposerJobTest.php
new file mode 100644
index 00000000..0110b99a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/EntityIdDisposerJobTest.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\EntityIdDisposerJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\EntityIdDisposerJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class EntityIdDisposerJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->getMockForAbstractClass();
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->setConnectionManager( $connectionManager );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ EntityIdDisposerJob::class,
+ new EntityIdDisposerJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testJobRun( $parameters ) {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $instance = new EntityIdDisposerJob(
+ $subject->getTitle(),
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function parametersProvider() {
+
+ $provider[] = [
+ []
+ ];
+
+ $provider[] = [
+ [ 'id' => 42 ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableRebuildJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableRebuildJobTest.php
new file mode 100644
index 00000000..3c18b202
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableRebuildJobTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\FulltextSearchTableRebuildJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\FulltextSearchTableRebuildJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FulltextSearchTableRebuildJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\FulltextSearchTableRebuildJob',
+ new FulltextSearchTableRebuildJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testRunJob( $parameters ) {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $instance = new FulltextSearchTableRebuildJob(
+ $subject->getTitle(),
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function parametersProvider() {
+
+ $provider[] = [
+ []
+ ];
+
+ $provider[] = [
+ [ 'table' => 'Foo' ]
+ ];
+
+ $provider[] = [
+ [ 'mode' => 'full' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableUpdateJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableUpdateJobTest.php
new file mode 100644
index 00000000..ce085a35
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/FulltextSearchTableUpdateJobTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\FulltextSearchTableUpdateJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\FulltextSearchTableUpdateJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FulltextSearchTableUpdateJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->testEnvironment->registerObject(
+ 'Store',
+ $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )->getMockForAbstractClass()
+ );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\FulltextSearchTableUpdateJob',
+ new FulltextSearchTableUpdateJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testJobRun( $parameters ) {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $instance = new FulltextSearchTableUpdateJob(
+ $subject->getTitle(),
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function parametersProvider() {
+
+ $provider[] = [
+ 'diff' => [ 1, 2 ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/NullJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/NullJobTest.php
new file mode 100644
index 00000000..58a25460
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/NullJobTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\MediaWiki\Jobs\NullJob;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\NullJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class NullJobTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\NullJob',
+ new NullJob( null )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testRunJob( $parameters ) {
+
+ $instance = new NullJob(
+ null,
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function parametersProvider() {
+
+ $provider[] = [
+ []
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ParserCachePurgeJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ParserCachePurgeJobTest.php
new file mode 100644
index 00000000..28ba1c62
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/ParserCachePurgeJobTest.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\ParserCachePurgeJob;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\ParserCachePurgeJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class ParserCachePurgeJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->getMockForAbstractClass();
+
+ $this->applicationFactory->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\ParserCachePurgeJob',
+ new ParserCachePurgeJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testJobWithIdList( $parameters ) {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $instance = new ParserCachePurgeJob(
+ $subject->getTitle(),
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function testSplitList() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $instance = new ParserCachePurgeJob(
+ $subject->getTitle()
+ );
+
+ $list = [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ new DIWikiPage( 'Foobar', 0 , '', '_QUERY123' )
+ ];
+
+ $this->assertEquals(
+ [ [ 'Foo#0##', 'Bar#0##', 'Foobar#0##' ], [ '_QUERY123' ] ],
+ $instance->splitList( $list )
+ );
+ }
+
+ public function parametersProvider() {
+
+ $provider[] = [
+ 'idlist' => [ 1, 2 ]
+ ];
+
+ $provider[] = [
+ 'idlist' => '1|2'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/PropertyStatisticsRebuildJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/PropertyStatisticsRebuildJobTest.php
new file mode 100644
index 00000000..5c6e3e6f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/PropertyStatisticsRebuildJobTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\PropertyStatisticsRebuildJob;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\PropertyStatisticsRebuildJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyStatisticsRebuildJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $row = new \stdClass;
+ $row->smw_title = 'Test';
+ $row->smw_id = 42;
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( new \FakeResultWrapper( [ $row ] ) ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\PropertyStatisticsRebuildJob',
+ new PropertyStatisticsRebuildJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testRunJob( $parameters ) {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $instance = new PropertyStatisticsRebuildJob(
+ $subject->getTitle(),
+ $parameters
+ );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function parametersProvider() {
+
+ $provider[] = [
+ []
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/RefreshJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/RefreshJobTest.php
new file mode 100644
index 00000000..b30e5fdf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/RefreshJobTest.php
@@ -0,0 +1,175 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Jobs\RefreshJob;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\RefreshJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class RefreshJobTest extends \PHPUnit_Framework_TestCase {
+
+ /** @var integer */
+ protected $controlRefreshDataIndex;
+
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->applicationFactory->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\RefreshJob',
+ new RefreshJob( $title )
+ );
+
+ // FIXME Delete SMWRefreshJob assertion after all
+ // references to SMWRefreshJob have been removed
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\RefreshJob',
+ new \SMWRefreshJob( $title )
+ );
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testRunJobOnMockStore( $parameters, $expected ) {
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $expectedToRun = $expected['spos'] === null ? $this->once() : $this->once();
+
+ $entityRebuildDispatcher = $this->getMockBuilder( '\SMW\SQLStore\EntityRebuildDispatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityRebuildDispatcher->expects( $this->any() )
+ ->method( 'rebuild' )
+ ->will( $this->returnValue( $parameters['spos'] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->setMethods( [ 'refreshData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $expectedToRun )
+ ->method( 'refreshData' )
+ ->will( $this->returnValue( $entityRebuildDispatcher ) );
+
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $instance = new RefreshJob( $title, $parameters );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue( $instance->run() );
+
+ $this->assertEquals(
+ $expected['progress'],
+ $instance->getProgress(),
+ "Asserts that the getProgress() returns {$expected['progress']}"
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function parameterDataProvider() {
+
+ $provider = [];
+
+ // #0 Empty
+ $provider[] = [
+ [
+ 'spos' => null
+ ],
+ [
+ 'progress' => 0,
+ 'spos' => null
+ ]
+ ];
+
+ // #1 Initial
+ $provider[] = [
+ [
+ 'spos' => 1,
+ 'prog' => 0,
+ 'rc' => 1
+ ],
+ [
+ 'progress' => 0,
+ 'spos' => 1
+ ]
+ ];
+
+ // #2
+ $provider[] = [
+ [
+ 'spos' => 1,
+ 'run' => 1,
+ 'prog' => 10,
+ 'rc' => 1
+ ],
+ [
+ 'progress' => 10,
+ 'spos' => 1
+ ]
+ ];
+
+ // #3 Initiates another run from the beginning
+ $provider[] = [
+ [
+ 'spos' => 0,
+ 'run' => 1,
+ 'prog' => 10,
+ 'rc' => 2
+ ],
+ [
+ 'progress' => 5,
+ 'spos' => 0
+ ]
+ ];
+
+ return $provider;
+
+ }
+
+ /**
+ * @see Store::refreshData
+ *
+ * @since 1.9
+ *
+ * @param integer $index
+ */
+ public function refreshDataCallback( &$index ) {
+ $this->controlRefreshDataIndex = $index;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateDispatcherJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateDispatcherJobTest.php
new file mode 100644
index 00000000..cf721cad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateDispatcherJobTest.php
@@ -0,0 +1,421 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\ApplicationFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\UpdateDispatcherJob;
+use SMW\SemanticData;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\UpdateDispatcherJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class UpdateDispatcherJobTest extends \PHPUnit_Framework_TestCase {
+
+ protected $expectedProperty;
+ protected $expectedSubjects;
+ private $semanticDataSerializer;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataSerializer = ApplicationFactory::getInstance()->newSerializerFactory()->newSemanticDataSerializer();
+
+ $this->testEnvironment = new TestEnvironment( [
+ 'smwgMainCacheType' => 'hash',
+ 'smwgEnableUpdateJobs' => false
+ ] );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\UpdateDispatcherJob',
+ new UpdateDispatcherJob( $title )
+ );
+ }
+
+ public function testPushToJobQueue() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new UpdateDispatcherJob( $title, [] );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertNull( $instance->pushToJobQueue() );
+ }
+
+ public function testChunkedJobWithListOnValidMembers() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new UpdateDispatcherJob( $title, [
+ 'job-list' => [
+ 'Foo#0##' => true,
+ 'Bar#102##'
+ ]
+ ] );
+
+ $instance->isEnabledJobQueue( false );
+ $instance->run();
+
+ $this->assertEquals(
+ 2,
+ $instance->getJobCount()
+ );
+ }
+
+ public function testChunkedJobWithListOnInvalidMembers() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new UpdateDispatcherJob( $title, [
+ 'job-list' => [
+ '|nulltitle#0##' => true,
+ 'deserlizeerror#0' => true
+ ]
+ ] );
+
+ $instance->isEnabledJobQueue( false );
+ $instance->run();
+
+ $this->assertEquals(
+ 0,
+ $instance->getJobCount()
+ );
+ }
+
+ public function testJobRunOnMainNamespace() {
+
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [
+ 'getProperties',
+ 'getInProperties' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getInProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateDispatcherJob( $title, [] );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue( $instance->run() );
+ }
+
+ public function testJobRunOnPropertyNamespace() {
+
+ $title = Title::newFromText( __METHOD__, SMW_NS_PROPERTY );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [
+ 'getProperties',
+ 'getInProperties',
+ 'getAllPropertySubjects',
+ 'getPropertySubjects' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getInProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getAllPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateDispatcherJob( $title, [] );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue( $instance->run() );
+ }
+
+ public function testJobRunOnRestrictedPool() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $semanticData = new SemanticData( $subject );
+ $semanticData->addPropertyObjectValue( new DIProperty( '42' ), $subject );
+
+ $parameters = [
+ 'semanticData' => $this->semanticDataSerializer->serialize( $semanticData ),
+ UpdateDispatcherJob::RESTRICTED_DISPATCH_POOL => true
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [
+ 'getAllPropertySubjects',
+ ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getAllPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateDispatcherJob( $title, $parameters );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ /**
+ * @dataProvider subjectDataProvider
+ */
+ public function testRunJobOnMockWithOutParameters( $setup, $expected ) {
+
+ $this->expectedProperty = $setup['property'];
+ $this->expectedSubjects = $setup['subjects'];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [
+ 'getAllPropertySubjects',
+ 'getPropertyValues',
+ 'getProperties',
+ 'getInProperties',
+ 'getPropertySubjects' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getAllPropertySubjects' )
+ ->will( $this->returnCallback( [ $this, 'mockStoreAllPropertySubjectsCallback' ] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromTitle( $setup['title'] ) ] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( $setup['properties'] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getInProperties' )
+ ->will( $this->returnValue( $setup['properties'] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateDispatcherJob( $setup['title'], $setup['parameters'] );
+ $instance->isEnabledJobQueue( false );
+ $instance->run();
+
+ $this->assertEquals(
+ $expected['count'],
+ $instance->getJobCount()
+ );
+ }
+
+ /**
+ * @dataProvider subjectDataProvider
+ */
+ public function testRunJobOnMockWithParameters( $setup, $expected ) {
+
+ $semanticData = new SemanticData(
+ DIWikiPage::newFromTitle( $setup['title'] )
+ );
+
+ $parameters = [
+ 'semanticData' => $this->semanticDataSerializer->serialize( $semanticData )
+ ] + $setup['parameters'];
+
+ $this->expectedProperty = $setup['property'];
+ $this->expectedSubjects = $setup['subjects'];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [
+ 'getAllPropertySubjects',
+ 'getPropertyValues',
+ 'getProperties',
+ 'getInProperties',
+ 'getPropertySubjects' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getAllPropertySubjects' )
+ ->will( $this->returnCallback( [ $this, 'mockStoreAllPropertySubjectsCallback' ] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromTitle( $setup['title'] ) ] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( $setup['properties'] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getInProperties' )
+ ->will( $this->returnValue( $setup['properties'] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateDispatcherJob( $setup['title'], $parameters );
+ $instance->isEnabledJobQueue( false );
+ $instance->run();
+
+ $this->assertEquals(
+ $expected['count'],
+ $instance->getJobCount()
+ );
+ }
+
+ public function subjectDataProvider() {
+
+ $provider = [];
+
+ $duplicate = DIWikiPage::newFromText( 'Foo' );
+
+ $subjects = [
+ $duplicate,
+ DIWikiPage::newFromText( 'Bar' ),
+ DIWikiPage::newFromText( 'Baz' ),
+ $duplicate,
+ DIWikiPage::newFromText( 'Yon' ),
+ DIWikiPage::newFromText( 'Yon' ),
+ DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY )
+ ];
+
+ $count = count( $subjects ) - 1; // eliminate duplicate count
+ $title = Title::newFromText( __METHOD__, SMW_NS_PROPERTY );
+ $property = DIProperty::newFromUserLabel( $title->getText() );
+
+ #0
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'subjects' => $subjects,
+ 'property' => $property,
+ 'properties' => [],
+ 'parameters' => []
+ ],
+ [
+ 'count' => 6
+ ]
+ ];
+
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+ $property = DIProperty::newFromUserLabel( $title->getText() );
+
+ #1
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'subjects' => [ DIWikiPage::newFromTitle( $title ) ],
+ 'property' => $property,
+ 'properties' => [ $property ],
+ 'parameters' => []
+ ],
+ [
+ 'count' => 1
+ ]
+ ];
+
+
+ #2
+ $duplicate = DIWikiPage::newFromText( 'Foo' );
+
+ $subjects = [
+ $duplicate,
+ DIWikiPage::newFromText( 'Bar' ),
+ DIWikiPage::newFromText( 'Baz' ),
+ $duplicate,
+ DIWikiPage::newFromText( 'Yon' ),
+ DIWikiPage::newFromText( 'Yon' ),
+ DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY )
+ ];
+
+ $title = Title::newFromText( __METHOD__, SMW_NS_PROPERTY );
+ $property = DIProperty::newFromUserLabel( $title->getText() );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'subjects' => $subjects,
+ 'property' => $property,
+ 'properties' => [],
+ 'parameters' => [ UpdateDispatcherJob::RESTRICTED_DISPATCH_POOL => true ]
+ ],
+ [
+ 'count' => 6
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * Returns an array of DIWikiPage objects if the expected property
+ * and the argument property are identical
+ *
+ * @see Store::getAllPropertySubjects
+ *
+ * @return DIWikiPage[]
+ */
+ public function mockStoreAllPropertySubjectsCallback( DIProperty $property ) {
+ return $this->expectedSubjects;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateJobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateJobTest.php
new file mode 100644
index 00000000..09e2bdc1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Jobs/UpdateJobTest.php
@@ -0,0 +1,325 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Jobs;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\UpdateJob;
+use SMW\Tests\TestEnvironment;
+use SMWDIBlob as DIBlob;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Jobs\UpdateJob
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class UpdateJobTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $semanticDataFactory;
+ private $semanticDataSerializer;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment( [
+ 'smwgMainCacheType' => 'hash',
+ 'smwgEnableUpdateJobs' => false,
+ 'smwgEnabledDeferredUpdate' => false,
+ 'smwgDVFeatures' => '',
+ 'smwgSemanticsEnabled' => false
+ ] );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'getPropertyValues', 'updateData' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->semanticDataFactory = $this->testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+ $this->semanticDataSerializer = \SMW\ApplicationFactory::getInstance()->newSerializerFactory()->newSemanticDataSerializer();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\UpdateJob',
+ new UpdateJob( $title )
+ );
+
+ // FIXME Delete SMWUpdateJob assertion after all
+ // references to SMWUpdateJob have been removed
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Jobs\UpdateJob',
+ new \SMWUpdateJob( $title )
+ );
+ }
+
+ public function testJobWithMissingParserOutput() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new UpdateJob( $title );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertFalse( $instance->run() );
+ }
+
+ public function testJobWithInvalidTitle() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( 0 ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->once() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->testEnvironment->registerObject( 'ContentParser', null );
+
+ $instance = new UpdateJob( $title );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue( $instance->run() );
+ }
+
+ public function testJobWithNoRevisionAvailable() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $contentParser = $this->getMockBuilder( '\SMW\ContentParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentParser->expects( $this->once() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( null ) );
+
+ $this->testEnvironment->registerObject( 'ContentParser', $contentParser );
+
+ $instance = new UpdateJob( $title );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertFalse( $instance->run() );
+ }
+
+ public function testJobWithValidRevision() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getDBkey' )
+ ->will( $this->returnValue( __METHOD__ ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( 0 ) );
+
+ $title->expects( $this->once() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $contentParser = $this->getMockBuilder( '\SMW\ContentParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentParser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( new \ParserOutput ) );
+
+ $this->testEnvironment->registerObject( 'ContentParser', $contentParser );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $idTable->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'clearData', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->once() )
+ ->method( 'clearData' );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateJob( $title );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue( $instance->run() );
+ }
+
+ public function testJobToCompareLastModified() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getDBkey' )
+ ->will( $this->returnValue( __METHOD__ ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( 0 ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $contentParser = $this->getMockBuilder( '\SMW\ContentParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentParser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( new \ParserOutput ) );
+
+ $this->testEnvironment->registerObject( 'ContentParser', $contentParser );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyValues', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateJob( $title, [ 'shallowUpdate' => true ] );
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue( $instance->run() );
+ }
+
+ public function testJobOnSerializedSemanticData() {
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'updateData' );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $semanticData = $this->semanticDataSerializer->serialize(
+ $this->semanticDataFactory->newEmptySemanticData( __METHOD__ )
+ );
+
+ $instance = new UpdateJob( $title,
+ [
+ UpdateJob::SEMANTIC_DATA => $semanticData
+ ]
+ );
+
+ $instance->isEnabledJobQueue( false );
+
+ $this->assertTrue(
+ $instance->run()
+ );
+ }
+
+ public function testJobOnChangePropagation() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY );
+
+ $semanticData = $this->semanticDataSerializer->serialize(
+ $this->semanticDataFactory->newEmptySemanticData( __METHOD__ )
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'updateData', 'getPropertyValues' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ new DIBlob( json_encode( $semanticData ) ) ] ) );
+
+ $store->expects( $this->once() )
+ ->method( 'updateData' );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new UpdateJob( $subject->getTitle(),
+ [
+ UpdateJob::CHANGE_PROP => $subject->getSerialization()
+ ]
+ );
+
+ $instance->isEnabledJobQueue( false );
+
+ $instance->run();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/LocalTimeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/LocalTimeTest.php
new file mode 100644
index 00000000..53745c88
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/LocalTimeTest.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use DateTime;
+use SMW\MediaWiki\LocalTime;
+
+/**
+ * @covers \SMW\MediaWiki\LocalTime
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class LocalTimeTest extends \PHPUnit_Framework_TestCase {
+
+ public function testNoModifiedLocalTime() {
+
+ $dateTime = LocalTime::getLocalizedTime(
+ new DateTime( '2017-08-01 10:00:00+00:00' )
+ );
+
+ $this->assertFalse(
+ $dateTime->hasLocalTimeCorrection
+ );
+ }
+
+ public function testModifiedTimeWithPositiveLocalTimeOffset() {
+
+ $dti = new DateTime( '2017-08-01 10:00:00+00:00' );
+
+ LocalTime::setLocalTimeOffset( 60 );
+ $dateTime = LocalTime::getLocalizedTime( $dti );
+
+ $this->assertTrue(
+ $dateTime->hasLocalTimeCorrection
+ );
+
+ $this->assertEquals(
+ '2017-08-01 11:00:00',
+ $dateTime->format( 'Y-m-d H:i:s' )
+ );
+ }
+
+ public function testModifiedTimeWithNegativeLocalTimeOffset() {
+
+ $dti = new DateTime( '2017-08-01 10:00:00+00:00' );
+
+ LocalTime::setLocalTimeOffset( -60 );
+ $dateTime = LocalTime::getLocalizedTime( $dti );
+
+ $this->assertTrue(
+ $dateTime->hasLocalTimeCorrection
+ );
+
+ $this->assertEquals(
+ '2017-08-01 09:00:00',
+ $dateTime->format( 'Y-m-d H:i:s' )
+ );
+ }
+
+ public function testModifiedTimeWithUserTimeCorrection() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( 'timecorrection' ) )
+ ->will( $this->returnValue( 'ZoneInfo|+120|Europe/Berlin' ) );
+
+ $dti = new DateTime( '2017-08-01 10:00:00+00:00' );
+
+ LocalTime::setLocalTimeOffset( 0 );
+ $dateTime = LocalTime::getLocalizedTime( $dti, $user );
+
+ $this->assertTrue(
+ $dateTime->hasLocalTimeCorrection
+ );
+
+ $this->assertEquals(
+ '2017-08-01 12:00:00',
+ $dateTime->format( 'Y-m-d H:i:s' )
+ );
+ }
+
+ public function testModifiedTimeWithUserTimeCorrectionOnInvalidZone() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( 'timecorrection' ) )
+ ->will( $this->returnValue( 'ZoneInfo|+125|Foo' ) );
+
+ $dti = new DateTime( '2017-08-01 10:00:00+00:00' );
+
+ $dateTime = LocalTime::getLocalizedTime( $dti, $user );
+
+ $this->assertTrue(
+ $dateTime->hasLocalTimeCorrection
+ );
+
+ $this->assertEquals(
+ '2017-08-01 12:05:00',
+ $dateTime->format( 'Y-m-d H:i:s' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MagicWordsFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MagicWordsFinderTest.php
new file mode 100644
index 00000000..68e58839
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MagicWordsFinderTest.php
@@ -0,0 +1,160 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use ParserOutput;
+use SMW\MediaWiki\MagicWordsFinder;
+
+/**
+ * @covers \SMW\MediaWiki\MagicWordsFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class MagicWordsFinderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MagicWordsFinder',
+ new MagicWordsFinder()
+ );
+
+ $parserOutput = $this->getMockBuilder( 'ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MagicWordsFinder',
+ new MagicWordsFinder( $parserOutput )
+ );
+ }
+
+ /**
+ * @dataProvider magicWordsProvider
+ */
+ public function testFindMagicWordInText( $magicWord, $text, $expectedText, $expectedWord ) {
+
+ $instance = new MagicWordsFinder();
+ $word = $instance->findMagicWordInText( $magicWord, $text );
+
+ $this->assertInternalType(
+ 'string',
+ $word
+ );
+
+ $this->assertEquals(
+ $expectedWord,
+ $word
+ );
+
+ $this->assertEquals(
+ $expectedText,
+ $text
+ );
+ }
+
+ public function testSetGetMagicWords() {
+
+ $instance = new MagicWordsFinder(
+ new ParserOutput()
+ );
+
+ $this->assertMagicWordFromParserOutput(
+ $instance,
+ [ 'Foo', '', 'Bar' ],
+ [ 'Foo', 'Bar' ]
+ );
+ }
+
+ public function testSetGetMagicWordsOnLegacyStorage() {
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\MagicWordsFinder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'hasExtensionData' ] )
+ ->getMock();
+
+ $instance->expects( $this->any() )
+ ->method( 'hasExtensionData' )
+ ->will( $this->returnValue( false ) );
+
+ $instance->setOutput( new ParserOutput() );
+
+ $this->assertMagicWordFromParserOutput(
+ $instance,
+ [ 'Foo', '', 'Bar' ],
+ [ 'Foo', 'Bar' ]
+ );
+ }
+
+ public function testNoPushOnEmptyMagicWordsList() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->never() )
+ ->method( 'setExtensionData' );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\MagicWordsFinder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'hasExtensionData' ] )
+ ->getMock();
+
+ $instance->expects( $this->any() )
+ ->method( 'hasExtensionData' )
+ ->will( $this->returnValue( true ) );
+
+ $instance->setOutput( $parserOutput );
+ $instance->pushMagicWordsToParserOutput( [] );
+ }
+
+ protected function assertMagicWordFromParserOutput( $instance, $magicWord, $expectedMagicWords ) {
+
+ $this->assertEmpty(
+ $instance->getMagicWords()
+ );
+
+ $instance->pushMagicWordsToParserOutput( $magicWord );
+
+ $this->assertEquals(
+ $expectedMagicWords,
+ $instance->getMagicWords()
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function magicWordsProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ 'SMW_NOFACTBOX',
+ 'Lorem ipsum dolor sit amet consectetuer auctor at quis',
+ 'Lorem ipsum dolor sit amet consectetuer auctor at quis',
+ ''
+ ];
+
+ $provider[] = [
+ 'SMW_NOFACTBOX',
+ 'Lorem ipsum dolor sit __NOFACTBOX__ amet consectetuer auctor at quis',
+ 'Lorem ipsum dolor sit amet consectetuer auctor at quis',
+ 'SMW_NOFACTBOX'
+ ];
+
+ $provider[] = [
+ 'SMW_SHOWFACTBOX',
+ 'Lorem ipsum dolor __NOFACTBOX__ sit amet consectetuer auctor at quis __SHOWFACTBOX__',
+ 'Lorem ipsum dolor __NOFACTBOX__ sit amet consectetuer auctor at quis ',
+ 'SMW_SHOWFACTBOX'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/ManualEntryLoggerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/ManualEntryLoggerTest.php
new file mode 100644
index 00000000..a69073b9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/ManualEntryLoggerTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\ManualEntryLogger;
+
+/**
+ * @covers \SMW\MediaWiki\ManualEntryLogger
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ManualEntryLoggerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\ManualEntryLogger',
+ new ManualEntryLogger()
+ );
+ }
+
+ public function testLogToTableForNonLoggableEvent() {
+
+ $instance = new ManualEntryLogger();
+
+ $this->assertNull(
+ $instance->log( 'Foo', 'Bar', 'Baz', 'Yui' )
+ );
+ }
+
+ public function testRegisterLoggableEventType() {
+
+ $manualLogEntry = $this->getMockBuilder( '\ManualLogEntry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $manualLogEntry->expects( $this->once() )
+ ->method( 'insert' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new ManualEntryLogger( $manualLogEntry );
+ $instance->registerLoggableEventType( 'Foo' );
+
+ $this->assertEquals(
+ 42,
+ $instance->log( 'Foo', 'Bar', 'Baz', 'Yui' )
+ );
+ }
+
+ public function testLogToTableForLoggableEvent() {
+
+ $manualLogEntry = $this->getMockBuilder( '\ManualLogEntry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $manualLogEntry->expects( $this->once() )
+ ->method( 'insert' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\ManualEntryLogger' )
+ ->setMethods( [ 'newManualLogEntryForType' ] )
+ ->getMock();
+
+ $instance->expects( $this->once() )
+ ->method( 'newManualLogEntryForType' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnValue( $manualLogEntry ) );
+
+ $instance->registerLoggableEventType( 'Foo' );
+
+ $this->assertInternalType(
+ 'integer',
+ $instance->log( 'Foo', 'Bar', 'Baz', 'Yui' )
+ );
+ }
+
+ public function testLogToTableForLoggableEventWithPerformer() {
+
+ $performer = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $manualLogEntry = $this->getMockBuilder( '\ManualLogEntry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $manualLogEntry->expects( $this->once() )
+ ->method( 'insert' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\ManualEntryLogger' )
+ ->setMethods( [ 'newManualLogEntryForType' ] )
+ ->getMock();
+
+ $instance->expects( $this->once() )
+ ->method( 'newManualLogEntryForType' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnValue( $manualLogEntry ) );
+
+ $instance->registerLoggableEventType( 'Foo' );
+
+ $this->assertInternalType(
+ 'integer',
+ $instance->log( 'Foo', $performer, 'Baz', 'Yui' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MediaWikiNsContentReaderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MediaWikiNsContentReaderTest.php
new file mode 100644
index 00000000..3fc113d1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MediaWikiNsContentReaderTest.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\MediaWikiNsContentReader;
+
+/**
+ * @covers \SMW\MediaWiki\MediaWikiNsContentReader
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class MediaWikiNsContentReaderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MediaWikiNsContentReader',
+ new MediaWikiNsContentReader()
+ );
+ }
+
+ public function testReadFromMessageCache() {
+
+ $instance = new MediaWikiNsContentReader();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->read( 'smw-desc' )
+ );
+ }
+
+ public function testTryToReadForInvalidTitle() {
+
+ $instance = new MediaWikiNsContentReader();
+
+ $this->assertEmpty(
+ $instance->read( '{}' )
+ );
+ }
+
+ public function testSkipMessageCache() {
+
+ $instance = new MediaWikiNsContentReader();
+ $instance->skipMessageCache();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->read( __METHOD__ )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MessageBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MessageBuilderTest.php
new file mode 100644
index 00000000..c09d9d44
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MessageBuilderTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\MessageBuilder;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\MessageBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class MessageBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MessageBuilder',
+ new MessageBuilder( $language )
+ );
+ }
+
+ public function testFormatNumberToText() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->once() )
+ ->method( 'formatNum' );
+
+ $instance = new MessageBuilder();
+
+ $instance
+ ->setLanguage( $language )
+ ->formatNumberToText( 42 );
+ }
+
+ public function testListToCommaSeparatedText() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->once() )
+ ->method( 'listToText' );
+
+ $context = $this->getMockBuilder( '\IContextSource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $context->expects( $this->once() )
+ ->method( 'getLanguage' )
+ ->will( $this->returnValue( $language ) );
+
+ $instance = new MessageBuilder();
+
+ $instance
+ ->setLanguageFromContext( $context )
+ ->listToCommaSeparatedText( [ 'a', 'b' ] );
+ }
+
+ public function testPrevNextToText() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->once() )
+ ->method( 'viewPrevNext' );
+
+ $instance = new MessageBuilder( $language );
+ $instance->prevNextToText( $title, 20, 0, [], false );
+ }
+
+ public function testGetForm() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new MessageBuilder( $language );
+
+ $this->assertInstanceOf(
+ '\Message',
+ $instance->getMessage( 'properties' )
+ );
+ }
+
+ public function testNullLanguageThrowsException() {
+
+ $instance = new MessageBuilder();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getMessage( 'properties' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MwCollaboratorFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MwCollaboratorFactoryTest.php
new file mode 100644
index 00000000..8fc196cf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/MwCollaboratorFactoryTest.php
@@ -0,0 +1,263 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\MwCollaboratorFactory;
+
+/**
+ * @covers \SMW\MediaWiki\MwCollaboratorFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class MwCollaboratorFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = $this->getMockBuilder( '\SMW\ApplicationFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MwCollaboratorFactory',
+ new MwCollaboratorFactory( $this->applicationFactory )
+ );
+ }
+
+ public function testCanConstructMessageBuilder() {
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MessageBuilder',
+ $instance->newMessageBuilder()
+ );
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MessageBuilder',
+ $instance->newMessageBuilder( $language )
+ );
+ }
+
+ public function testCanConstructMagicWordsFinder() {
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MagicWordsFinder',
+ $instance->newMagicWordsFinder()
+ );
+ }
+
+ public function testCanConstructRedirectTargetFinder() {
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\RedirectTargetFinder',
+ $instance->newRedirectTargetFinder()
+ );
+ }
+
+ public function testCanConstructDeepRedirectTargetResolver() {
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->applicationFactory->expects( $this->atLeastOnce() )
+ ->method( 'newPageCreator' )
+ ->will( $this->returnValue( $pageCreator ) );
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\DeepRedirectTargetResolver',
+ $instance->newDeepRedirectTargetResolver()
+ );
+ }
+
+ public function testCanConstructHtmlFormRenderer() {
+
+ $instance = new MwCollaboratorFactory( new ApplicationFactory() );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlFormRenderer',
+ $instance->newHtmlFormRenderer( $title )
+ );
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlFormRenderer',
+ $instance->newHtmlFormRenderer( $title, $language )
+ );
+ }
+
+ public function testCanConstructHtmlTableRenderer() {
+
+ $instance = new MwCollaboratorFactory( new ApplicationFactory() );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlTableRenderer',
+ $instance->newHtmlTableRenderer()
+ );
+ }
+
+ public function testCanConstructHtmlColumnListRenderer() {
+
+ $instance = new MwCollaboratorFactory( new ApplicationFactory() );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlColumnListRenderer',
+ $instance->newHtmlColumnListRenderer()
+ );
+ }
+
+ public function testCanConstructLoadBalancerConnectionProvider() {
+
+ $instance = new MwCollaboratorFactory( new ApplicationFactory() );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Connection\LoadBalancerConnectionProvider',
+ $instance->newLoadBalancerConnectionProvider( DB_SLAVE )
+ );
+ }
+
+ public function testCanConstructConnectionProvider() {
+
+ $settings = $this->getMockBuilder( '\SMW\Settings' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $logger = $this->getMockBuilder( '\Psr\Log\LoggerInterface' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $settings->expects( $this->atLeastOnce() )
+ ->method( 'get' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->applicationFactory->expects( $this->atLeastOnce() )
+ ->method( 'getSettings' )
+ ->will( $this->returnValue( $settings ) );
+
+ $this->applicationFactory->expects( $this->atLeastOnce() )
+ ->method( 'getMediaWikiLogger' )
+ ->will( $this->returnValue( $logger ) );
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Connection\ConnectionProvider',
+ $instance->newConnectionProvider()
+ );
+ }
+
+ public function testCanConstructPageInfoProvider() {
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\PageInfoProvider',
+ $instance->newPageInfoProvider( $wikiPage )
+ );
+ }
+
+ public function testCanConstructEditInfoProvider() {
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\EditInfoProvider',
+ $instance->newEditInfoProvider( $wikiPage, $revision )
+ );
+ }
+
+ public function testCanConstructWikitextTemplateRenderer() {
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\WikitextTemplateRenderer',
+ $instance->newWikitextTemplateRenderer()
+ );
+ }
+
+ public function testCanConstructHtmlTemplateRenderer() {
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlTemplateRenderer',
+ $instance->newHtmlTemplateRenderer( $parser )
+ );
+ }
+
+ public function testCanConstructMediaWikiNsContentReader() {
+
+ $instance = new MwCollaboratorFactory(
+ $this->applicationFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\MediaWikiNsContentReader',
+ $instance->newMediaWikiNsContentReader()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageCreatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageCreatorTest.php
new file mode 100644
index 00000000..1d6d525a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageCreatorTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\PageCreator;
+use SMW\Tests\Utils\Mock\MockTitle;
+
+/**
+ * @covers \SMW\MediaWiki\PageCreator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class PageCreatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\PageCreator',
+ new PageCreator()
+ );
+ }
+
+ public function testCreatePage() {
+
+ $instance = new PageCreator();
+
+ $this->assertInstanceOf(
+ '\WikiPage',
+ $instance->createPage( MockTitle::buildMock( __METHOD__ ) )
+ );
+ }
+
+ public function testCreateFilePage() {
+
+ $instance = new PageCreator();
+
+ $this->assertInstanceOf(
+ '\WikiFilePage',
+ $instance->createFilePage( MockTitle::buildMock( __METHOD__ ) )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageInfoProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageInfoProviderTest.php
new file mode 100644
index 00000000..8f61da28
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageInfoProviderTest.php
@@ -0,0 +1,368 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\PageInfoProvider;
+use SMW\Tests\Utils\Mock\MockTitle;
+
+/**
+ * @covers \SMW\MediaWiki\PageInfoProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class PageInfoProviderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $wikipage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\PageInfoProvider',
+ new PageInfoProvider( $wikipage )
+ );
+ }
+
+ public function testWikiPage_TYPE_MODIFICATION_DATE() {
+
+ $instance = $this->constructPageInfoProviderInstance(
+ [
+ 'wikiPage' => [ 'getTimestamp' => 1272508903 ],
+ 'revision' => [],
+ 'user' => [],
+ ]
+ );
+
+ $this->assertEquals( 1272508903, $instance->getModificationDate() );
+ }
+
+ public function testWikiPage_TYPE_CREATION_DATE() {
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $revision->expects( $this->any() )
+ ->method( 'getTimestamp' )
+ ->will( $this->returnValue( 1272508903 ) );
+
+ $title = MockTitle::buildMock( 'Lula' );
+
+ $title->expects( $this->any() )
+ ->method( 'getFirstRevision' )
+ ->will( $this->returnValue( $revision ) );
+
+ $instance = $this->constructPageInfoProviderInstance(
+ [
+ 'wikiPage' => [ 'getTitle' => $title ],
+ 'revision' => [],
+ 'user' => [],
+ ]
+ );
+
+ $this->assertEquals( 1272508903, $instance->getCreationDate() );
+ }
+
+ /**
+ * @dataProvider parentIdProvider
+ */
+ public function testWikiPage_TYPE_NEW_PAGE_ForRevision( $parentId, $expected ) {
+
+ $instance = $this->constructPageInfoProviderInstance(
+ [
+ 'wikiPage' => [],
+ 'revision' => [ 'getParentId' => $parentId ],
+ 'user' => [],
+ ]
+ );
+
+ $this->assertEquals( $expected, $instance->isNewPage() );
+ }
+
+ /**
+ * @dataProvider parentIdProvider
+ */
+ public function testWikiPage_TYPE_NEW_PAGE( $parentId, $expected ) {
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $revision->expects( $this->any() )
+ ->method( 'getParentId' )
+ ->will( $this->returnValue( $parentId ) );
+
+ $instance = $this->constructPageInfoProviderInstance(
+ [
+ 'wikiPage' => [ 'getRevision' => $revision ],
+ 'revision' => [ ],
+ 'user' => [],
+ ]
+ );
+
+ $this->assertEquals( $expected, $instance->isNewPage() );
+ }
+
+ public function parentIdProvider() {
+
+ $provider = [
+ [ 90001, false ],
+ [ null , true ]
+ ];
+
+ return $provider;
+ }
+
+ public function testWikiPage_TYPE_LAST_EDITOR() {
+
+ $userPage = MockTitle::buildMock( 'Lula' );
+
+ $userPage->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_USER ) );
+
+ $instance = $this->constructPageInfoProviderInstance(
+ [
+ 'wikiPage' => [],
+ 'revision' => [],
+ 'user' => [ 'getUserPage' => $userPage ],
+ ]
+ );
+
+ $this->assertEquals( $userPage, $instance->getLastEditor() );
+ }
+
+ public function constructPageInfoProviderInstance( array $parameters ) {
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $parameters['wikiPage'] as $method => $returnValue ) {
+ $wikiPage->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnValue( $returnValue ) );
+ }
+
+ $revision = $this->getMockBuilder( '\Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $parameters['revision'] as $method => $returnValue ) {
+ $revision->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnValue( $returnValue ) );
+ }
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $parameters['user'] as $method => $returnValue ) {
+ $user->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnValue( $returnValue ) );
+ }
+
+ return new PageInfoProvider(
+ $wikiPage,
+ ( $parameters['revision'] !== [] ? $revision : null ),
+ ( $parameters['user'] !== [] ? $user : null )
+ );
+ }
+
+ /**
+ * @dataProvider uploadStatusWikiFilePageDataProvider
+ */
+ public function testWikiFilePage_TYPE_NEW_PAGE( $uploadStatus, $expected ) {
+
+ $wikiFilePage = $this->getMockBuilder( '\WikiFilePage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ if ( $uploadStatus !== null ) {
+ $wikiFilePage->smwFileReUploadStatus = $uploadStatus;
+ }
+
+ $instance = new PageInfoProvider( $wikiFilePage );
+
+ $this->assertEquals( $expected, $instance->isNewPage() );
+ }
+
+ /**
+ * @dataProvider mediaTypeWikiFilePageDataProvider
+ */
+ public function testWikiFilePage_MEDIA_TYPE( $file, $expected ) {
+
+ $wikiFilePage = $this->getMockBuilder( '\WikiFilePage' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isFilePage', 'getFile' ] )
+ ->getMock();
+
+ $wikiFilePage->expects( $this->any() )
+ ->method( 'isFilePage' )
+ ->will( $this->returnValue( true ) );
+
+ $wikiFilePage->expects( $this->any() )
+ ->method( 'getFile' )
+ ->will( $this->returnValue( $file ) );
+
+ $instance = new PageInfoProvider( $wikiFilePage );
+
+ $this->assertEquals( $expected, $instance->getMediaType() );
+ }
+
+ /**
+ * @dataProvider mimeTypeWikiFilePageDataProvider
+ */
+ public function testWikiFilePage_MIME_TYPE( $file, $expected ) {
+
+ $wikiFilePage = $this->getMockBuilder( '\WikiFilePage' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isFilePage', 'getFile' ] )
+ ->getMock();
+
+ $wikiFilePage->expects( $this->any() )
+ ->method( 'isFilePage' )
+ ->will( $this->returnValue( true ) );
+
+ $wikiFilePage->expects( $this->any() )
+ ->method( 'getFile' )
+ ->will( $this->returnValue( $file ) );
+
+ $instance = new PageInfoProvider( $wikiFilePage );
+
+ $this->assertEquals( $expected, $instance->getMimeType() );
+ }
+
+ public function testWikiPage_MEDIA_TYPE() {
+
+ $wikiFilePage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PageInfoProvider( $wikiFilePage );
+
+ $this->assertEquals( null, $instance->getMediaType() );
+ }
+
+ public function testWikiPage_MIME_TYPE() {
+
+ $wikiFilePage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PageInfoProvider( $wikiFilePage );
+
+ $this->assertEquals( null, $instance->getMimeType() );
+ }
+
+ public function testWikiPage_NativeData() {
+
+ $content = $this->getMockBuilder( '\Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content->expects( $this->any() )
+ ->method( 'getNativeData' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( $content ) );
+
+ $instance = new PageInfoProvider( $wikiPage );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getNativeData()
+ );
+ }
+
+ public function testWikiPage_NativeData_Null() {
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $this->any() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( null ) );
+
+ $instance = new PageInfoProvider( $wikiPage );
+
+ $this->assertEquals(
+ '',
+ $instance->getNativeData()
+ );
+ }
+
+ public function uploadStatusWikiFilePageDataProvider() {
+
+ $provider = [
+ [ null, false ],
+ [ false, true ],
+ [ true , false ]
+ ];
+
+ return $provider;
+ }
+
+ public function mediaTypeWikiFilePageDataProvider() {
+
+ $fileWithMedia = $this->getMockBuilder( '\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $fileWithMedia->expects( $this->any() )
+ ->method( 'getMediaType' )
+ ->will( $this->returnValue( 'FooMedia' ) );
+
+ $fileNullMedia = $this->getMockBuilder( '\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $fileNullMedia->expects( $this->any() )
+ ->method( 'getMediaType' )
+ ->will( $this->returnValue( null ) );
+
+ $provider[] = [ $fileWithMedia, 'FooMedia' ];
+ $provider[] = [ $fileNullMedia, null ];
+
+ return $provider;
+ }
+
+ public function mimeTypeWikiFilePageDataProvider() {
+
+ $fileWithMime = $this->getMockBuilder( '\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $fileWithMime->expects( $this->any() )
+ ->method( 'getMimeType' )
+ ->will( $this->returnValue( 'FooMime' ) );
+
+ $fileNullMime = $this->getMockBuilder( '\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $fileNullMime->expects( $this->any() )
+ ->method( 'getMediaType' )
+ ->will( $this->returnValue( null ) );
+
+ $provider[] = [ $fileWithMime, 'FooMime' ];
+ $provider[] = [ $fileNullMime, null ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageUpdaterTest.php
new file mode 100644
index 00000000..36094c68
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/PageUpdaterTest.php
@@ -0,0 +1,311 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\PageUpdater;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\PageUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PageUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+ private $spyLogger;
+
+ protected function setUp() {
+ parent::setup();
+
+ $this->spyLogger = TestEnvironment::newSpyLogger();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\PageUpdater',
+ new PageUpdater()
+ );
+ }
+
+ public function testCanUpdate() {
+
+ $instance = new PageUpdater();
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->canUpdate()
+ );
+ }
+
+ /**
+ * @dataProvider purgeMethodProvider
+ */
+ public function testPurge( $purgeMethod, $titleMethod ) {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->once() )
+ ->method( $titleMethod );
+
+ $instance = new PageUpdater();
+ $instance->addPage( $title );
+
+ call_user_func( [ $instance, $purgeMethod ] );
+ }
+
+ public function testDisablePurgeHtmlCache() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->never() )
+ ->method( 'touchLinks' );
+
+ $instance = new PageUpdater();
+ $instance->addPage( $title );
+
+ $instance->isHtmlCacheUpdate( false );
+ $instance->doPurgeHtmlCache();
+ }
+
+ public function testFilterDuplicatePages() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->exactly( 2 ) )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->once() )
+ ->method( 'invalidateCache' );
+
+ $instance = new PageUpdater();
+ $instance->addPage( $title );
+ $instance->addPage( $title );
+
+ $instance->doPurgeParserCache();
+ }
+
+ /**
+ * @dataProvider purgeMethodProvider
+ */
+ public function testPurgeOnTransactionIdle( $purgeMethod, $titleMethod ) {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->once() )
+ ->method( $titleMethod );
+
+ $instance = new PageUpdater();
+ $instance->addPage( $title );
+
+ $instance->waitOnTransactionIdle();
+
+ call_user_func( [ $instance, $purgeMethod ] );
+
+ $instance->doUpdate();
+ }
+
+ /**
+ * @dataProvider purgeMethodProvider
+ */
+ public function testPurgeWillNotWaitOnTransactionIdleForMissingConnection( $purgeMethod, $titleMethod ) {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->once() )
+ ->method( $titleMethod );
+
+ $instance = new PageUpdater();
+ $instance->addPage( $title );
+
+ $instance->waitOnTransactionIdle();
+
+ call_user_func( [ $instance, $purgeMethod ] );
+
+ $instance->doUpdate();
+ }
+
+ /**
+ * @dataProvider purgeMethodProvider
+ */
+ public function testPurgeWillNotWaitOnTransactionIdleWhenCommandLineIsTrue( $purgeMethod, $titleMethod ) {
+
+ $this->connection->expects( $this->never() )
+ ->method( 'onTransactionIdle' );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->once() )
+ ->method( $titleMethod );
+
+ $instance = new PageUpdater( $this->connection );
+ $instance->addPage( $title );
+
+ $instance->waitOnTransactionIdle();
+
+ call_user_func( [ $instance, $purgeMethod ] );
+
+ $instance->doUpdate();
+ }
+
+ public function testAddNullPage() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->never() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new PageUpdater();
+ $instance->addPage( null );
+ }
+
+ /**
+ * @dataProvider purgeMethodProvider
+ */
+ public function testPushPendingWaitableUpdate( $purgeMethod, $titleMethod ) {
+
+ $transactionalCallableUpdate = $this->getMockBuilder( '\SMW\MediaWiki\Deferred\TransactionalCallableUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $transactionalCallableUpdate->expects( $this->once() )
+ ->method( 'pushUpdate' );
+
+ $transactionalCallableUpdate->expects( $this->once() )
+ ->method( 'setFingerprint' )
+ ->with( $this->equalTo( 'Foobar' ) );
+
+ $transactionalCallableUpdate->expects( $this->once() )
+ ->method( 'waitOnTransactionIdle' );
+
+ $transactionalCallableUpdate->expects( $this->once() )
+ ->method( 'markAsPending' );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new PageUpdater(
+ $this->connection,
+ $transactionalCallableUpdate
+ );
+
+ $instance->addPage( $title );
+ $instance->setFingerprint( 'Foobar' );
+
+ $instance->markAsPending();
+ $instance->waitOnTransactionIdle();
+
+ call_user_func( [ $instance, $purgeMethod ] );
+
+ $instance->pushUpdate();
+ }
+
+ public function testPurgeCacheAsPoolPurge() {
+
+ $row = new \stdClass;
+ $row->page_id = 42;
+
+ $this->connection->expects( $this->once() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'update' );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) {
+ return call_user_func( $callback ); }
+ ) );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->never() )
+ ->method( 'invalidateCache' );
+
+ $instance = new PageUpdater( $this->connection );
+ $instance->setLogger( $this->spyLogger );
+ $instance->addPage( $title );
+
+ $instance->waitOnTransactionIdle();
+ $instance->doPurgeParserCacheAsPool();
+ }
+
+ public function purgeMethodProvider() {
+
+ $provider[] = [
+ 'doPurgeParserCache',
+ 'invalidateCache'
+ ];
+
+
+ $provider[] = [
+ 'doPurgeHtmlCache',
+ 'touchLinks'
+ ];
+
+ $provider[] = [
+ 'doPurgeWebCache',
+ 'purgeSquid'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/RedirectTargetFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/RedirectTargetFinderTest.php
new file mode 100644
index 00000000..0d0056ca
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/RedirectTargetFinderTest.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\RedirectTargetFinder;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\RedirectTargetFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class RedirectTargetFinderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\RedirectTargetFinder',
+ new RedirectTargetFinder()
+ );
+ }
+
+ /**
+ * @dataProvider redirectTextProvider
+ */
+ public function testFindRedirectTargetFromText( $text, $expectedHasTarget, $expectedGetTarget ) {
+
+ $instance = new RedirectTargetFinder();
+ $instance->findRedirectTargetFromText( $text );
+
+ $this->assertEquals(
+ $expectedHasTarget,
+ $instance->hasRedirectTarget()
+ );
+
+ $this->assertEquals(
+ $expectedGetTarget,
+ $instance->getRedirectTarget()
+ );
+ }
+
+ /**
+ * @dataProvider redirectTextProvider
+ */
+ public function testInjectedRedirectTargetOverridesTextFinder( $text ) {
+
+ $directRedirectTarget = Title::newFromText( 'Foo' );
+
+ $instance = new RedirectTargetFinder();
+ $instance->setRedirectTarget( $directRedirectTarget );
+ $instance->findRedirectTargetFromText( $text );
+
+ $this->assertTrue(
+ $instance->hasRedirectTarget()
+ );
+
+ $this->assertEquals(
+ $directRedirectTarget,
+ $instance->getRedirectTarget()
+ );
+ }
+
+ public function redirectTextProvider() {
+
+ $provider[] = [ '#REDIRECT [[:Lala]]', true, Title::newFromText( 'Lala' ) ];
+ $provider[] = [ '#REDIRECT [[Lala]]', true, Title::newFromText( 'Lala' ) ];
+ $provider[] = [ '[[:Lala]]', false, null ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlColumnListRendererTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlColumnListRendererTest.php
new file mode 100644
index 00000000..70e244ad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlColumnListRendererTest.php
@@ -0,0 +1,261 @@
+<?php
+
+namespace SMW\Test\MediaWiki\Renderer;
+
+use SMW\MediaWiki\Renderer\HtmlColumnListRenderer;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Renderer\HtmlColumnListRenderer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class HtmlColumnListFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlColumnListRenderer',
+ new HtmlColumnListRenderer()
+ );
+ }
+
+ public function testDefaultColumnUnorderedList() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance->addContentsByIndex( [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Ichi', 'Ni' ]
+ ] );
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:100%;" dir="ltr">',
+ '<div class="smw-column-header">a</div><ul><li>Foo</li><li>Bar</li></ul>',
+ '<div class="smw-column-header">B</div><ul><li>Ichi</li><li>Ni</li></ul></div>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testTwoColumnUnorderedList() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance->setNumberOfColumns( 2 );
+
+ $instance->addContentsByIndex( [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Baz', 'Fom', 'Fin', 'Fum' ]
+ ] );
+
+ $listContinuesAbbrev = wfMessage( 'listingcontinuesabbrev' )->text();
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">a</div>',
+ '<ul><li>Foo</li><li>Bar</li></ul>',
+ '<div class="smw-column-header">B</div><ul><li>Baz</li></ul></div> <!-- end column -->',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">B ' . $listContinuesAbbrev .'</div>',
+ '<ul start=4><li>Fom</li><li>Fin</li><li>Fum</li></ul></div> <!-- end column -->',
+ '<br style="clear: both;"/></div>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testThreeColumnUnorderedList() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance->setNumberOfColumns( 3 );
+
+ $instance->addContentsByIndex( [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Ichi', 'Ni' ]
+ ] );
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:33%;" dir="ltr">',
+ '<div class="smw-column-header">a</div><ul><li>Foo</li><li>Bar</li></ul></div>',
+ '<div class="smw-column" style="width:33%;" dir="ltr">',
+ '<div class="smw-column-header">B</div><ul><li>Ichi</li><li>Ni</li></ul></div>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testTwoColumnOrderedList() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance
+ ->setNumberOfColumns( 2 )
+ ->setListType( 'ol' );
+
+ $instance->addContentsByIndex( [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Ichi', 'Ni' ]
+ ] );
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">a</div><ol><li>Foo</li><li>Bar</li></ol></div> <!-- end column -->',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">B</div><ol><li>Ichi</li><li>Ni</li></ol></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testTwoColumnOrderedListNoHeader() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance
+ ->setNumberOfColumns( 2 )
+ ->setColumnListClass( 'foo-class' )
+ ->setColumnClass( 'bar-class' )
+ ->setListType( 'ul' );
+
+ $instance->addContentsByNoIndex(
+ [ 'Foo', 'Baz', 'Bar' ]
+ );
+
+ $expected = [
+ '<div class="foo-class" dir="ltr">',
+ '<div class="bar-class" style="width:50%;" dir="ltr">',
+ '<ul start=1><li>Foo</li><li>Baz</li></ul></div> <!-- end column -->',
+ '<div class="bar-class" style="width:50%;" dir="ltr">',
+ '<ul start=3><li>Bar</li></ul></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testResponsiveColumnsToBeDeterminedByBrowser() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance->setColumnListClass( 'foo-class' )
+ ->setNumberOfColumns( 2 ) // being set to 1 when it is responsive
+ ->setColumnClass( 'bar-responsive' )
+ ->setColumnRTLDirectionalityState( true )
+ ->setListType( 'ul' );
+
+ $instance->addContentsByNoIndex(
+ [ 'Foo', 'Baz', 'Bar' ]
+ );
+
+ $expected = [
+ '<div class="foo-class" dir="rtl"><div class="bar-responsive" style="width:100%;" dir="rtl">',
+ '<ul start=1><li>Foo</li><li>Baz</li><li>Bar</li></ul></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testItemListWithAttributes() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance->setColumnListClass( 'foo-class' )
+ ->setNumberOfColumns( 2 ) // being set to 1 when it is responsive
+ ->setColumnClass( 'bar-responsive' )
+ ->setColumnRTLDirectionalityState( true )
+ ->setListType( 'ul' );
+
+ $instance->addContentsByNoIndex(
+ [ 'Foo', 'Baz', 'Bar' ]
+ );
+
+ $instance->setItemAttributes(
+ [
+ md5( 'Foo' ) => [
+ 'id' => 123
+ ],
+ md5( 'Bar' ) => 456
+ ]
+ );
+
+ $expected = [
+ '<div class="foo-class" dir="rtl"><div class="bar-responsive" style="width:100%;" dir="rtl">',
+ '<ul start=1><li id="123">Foo</li><li>Baz</li><li 0="456">Bar</li></ul></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testOListWithAttributes() {
+
+ $instance = new HtmlColumnListRenderer();
+
+ $instance->setColumnListClass( 'foo-class' )
+ ->setNumberOfColumns( 2 ) // being set to 1 when it is responsive
+ ->setColumnClass( 'bar-responsive' )
+ ->setColumnRTLDirectionalityState( true )
+ ->setListType( 'ol', 'i' );
+
+ $instance->addContentsByNoIndex(
+ [ 'Foo', 'Baz', 'Bar' ]
+ );
+
+ $instance->setItemAttributes(
+ [
+ md5( 'Foo' ) => [
+ 'id' => 123
+ ],
+ md5( 'Bar' ) => 456
+ ]
+ );
+
+ $expected = [
+ '<div class="foo-class" dir="rtl"><div class="bar-responsive" style="width:100%;" dir="rtl">',
+ '<ol type=i start=1><li id="123">Foo</li><li>Baz</li><li 0="456">Bar</li></ol></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlFormRendererTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlFormRendererTest.php
new file mode 100644
index 00000000..fde461ab
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlFormRendererTest.php
@@ -0,0 +1,225 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Renderer;
+
+use SMW\MediaWiki\Renderer\HtmlFormRenderer;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Renderer\HtmlFormRenderer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class HtmlFormRendererTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlFormRenderer',
+ new HtmlFormRenderer( $title, $messageBuilder )
+ );
+ }
+
+ public function testGetMessageBuilder() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new HtmlFormRenderer( $title, $messageBuilder );
+
+ $this->assertSame(
+ $messageBuilder,
+ $instance->getMessageBuilder()
+ );
+ }
+
+ public function testGetForm() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->any() )
+ ->method( 'title' )
+ ->will( $this->returnSelf() );
+
+ $message->expects( $this->any() )
+ ->method( 'numParams' )
+ ->will( $this->returnSelf() );
+
+ $message->expects( $this->any() )
+ ->method( 'rawParams' )
+ ->will( $this->returnSelf() );
+
+ $message->expects( $this->any() )
+ ->method( 'text' )
+ ->will( $this->returnValue( 'SomeText' ) );
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageBuilder->expects( $this->any() )
+ ->method( 'getMessage' )
+ ->will( $this->returnValue( $message ) );
+
+ $instance = new HtmlFormRenderer( $title, $messageBuilder );
+
+ $instance
+ ->setName( 'SomeForm' )
+ ->withFieldset()
+ ->addParagraph( 'SomeDescription' )
+ ->addQueryParameter( 'SomeQueryParameter', 'SomeQueryValue' )
+ ->addPaging( 10, 0, 5 )
+ ->addHorizontalRule()
+ ->addInputField( 'SomeInputFieldLabel', 'foo', 'Foo', 'FooId', 333 )
+ ->addLineBreak()
+ ->addNonBreakingSpace()
+ ->addInputField( 'AnotherInputFieldLabel', 'AnotherInputFieldName', 'AnotherInputFieldValue' )
+ ->addSubmitButton( 'FindFoo' );
+
+ $expected = [
+ 'form id="smw-form-SomeForm" name="SomeForm" method="get"',
+ '<p class="smw-form-paragraph">SomeDescription</p>',
+ 'input name="foo" size="333" value="Foo" id="FooId"',
+ 'input name="AnotherInputFieldName" size="20" value="AnotherInputFieldValue" id="AnotherInputFieldName"',
+ 'input type="submit" value="FindFoo"',
+ //'<br />&nbsp;' MW 1.27 <br/>&nbsp;
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getForm()
+ );
+ }
+
+ public function testOptionsSelecList() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->any() )
+ ->method( 'text' )
+ ->will( $this->returnValue( 'SomeText' ) );
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageBuilder->expects( $this->any() )
+ ->method( 'getMessage' )
+ ->will( $this->returnValue( $message ) );
+
+ $instance = new HtmlFormRenderer( $title, $messageBuilder );
+
+ $instance
+ ->setName( 'optionsSelecListForm' )
+ ->withFieldset()
+ ->setMethod( 'isNeithergetNorPostMethodUseDefaultInstead' )
+ ->addOptionSelectList(
+ 'optionlistLabel',
+ 'optionlistName',
+ 'b',
+ [ 'f' => 'foo', 'b' =>'bar' ],
+ 'optionslistId');
+
+ $expected = [
+ 'form id="smw-form-optionsSelecListForm" name="optionsSelecListForm" method="get"',
+ '<fieldset id="smw-form-fieldset-optionsSelecListForm">',
+ '<label for="optionslistId">optionlistLabel</label>&#160;',
+ '<select name="optionlistName" id="optionslistId" class="smw-form-select">',
+ '<option value="b" selected="">bar</option>',
+ '<option value="f">foo</option>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getForm()
+ );
+ }
+
+ public function testCheckbox() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->any() )
+ ->method( 'text' )
+ ->will( $this->returnValue( 'SomeText' ) );
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageBuilder->expects( $this->any() )
+ ->method( 'getMessage' )
+ ->will( $this->returnValue( $message ) );
+
+ $instance = new HtmlFormRenderer( $title, $messageBuilder );
+
+ $instance
+ ->setName( 'checkboxForm' )
+ ->addHeader( 'invalidLevel', 'someHeader' )
+ ->withFieldset()
+ ->setMethod( 'post' )
+ ->setActionUrl( 'http://example.org/foo' )
+ ->addCheckbox(
+ 'checkboxLabel',
+ 'checkboxName',
+ true,
+ 'checkBoxId' );
+
+ $expected = [
+ '<form id="smw-form-checkboxForm" name="checkboxForm" method="post" action="http://example.org/foo">',
+ '<h2>someHeader</h2>',
+ '<fieldset id="smw-form-fieldset-checkboxForm">',
+ '<input name="checkboxName" type="checkbox" value="1" checked="checked" id="checkboxName" class="smw-form-checkbox" />',
+ '<label for="checkboxName" class="smw-form-checkbox">checkboxLabel</label>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getForm()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTableRendererTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTableRendererTest.php
new file mode 100644
index 00000000..6cb9b2b6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTableRendererTest.php
@@ -0,0 +1,178 @@
+<?php
+
+namespace SMW\Test\MediaWiki\Renderer;
+
+use SMW\MediaWiki\Renderer\HtmlTableRenderer;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Renderer\HtmlTableRenderer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class HtmlTableRendererTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlTableRenderer',
+ new HtmlTableRenderer()
+ );
+ }
+
+ public function testAddHeaderItem() {
+
+ $instance = new HtmlTableRenderer();
+ $instance->addHeaderItem( 'span', 'lala' );
+
+ $this->stringValidator->assertThatStringContains(
+ '<span>lala</span>',
+ $instance->getHeaderItems()
+ );
+ }
+
+ public function testAddTableHeader() {
+
+ $instance = new HtmlTableRenderer();
+ $instance->addHeader( 'lala' );
+
+ $this->stringValidator->assertThatStringContains(
+ '<th>lala</th>',
+ $instance->getHtml()
+ );
+
+ $instance = new HtmlTableRenderer( true );
+ $instance->addHeader( 'lila' );
+
+ $this->stringValidator->assertThatStringContains(
+ '<thead><th>lila</th></thead>',
+ $instance->getHtml()
+ );
+ }
+
+ public function testAddTableRow() {
+
+ $instance = new HtmlTableRenderer();
+
+ $instance
+ ->addCell( 'lala', [ 'class' => 'foo' ] )
+ ->addRow()
+ ->addCell( 'lula' )
+ ->addRow();
+
+ $this->stringValidator->assertThatStringContains(
+ '<tr class="row-odd"><td class="foo">lala</td></tr><tr class="row-even"><td>lula</td></tr>',
+ $instance->getHtml()
+ );
+
+ $instance = new HtmlTableRenderer();
+
+ $instance
+ ->setHtmlContext( true )
+ ->addCell( 'lila' )
+ ->addRow();
+
+ $this->stringValidator->assertThatStringContains(
+ '<tbody><tr class="row-odd"><td>lila</td></tr></tbody>',
+ $instance->getHtml()
+ );
+ }
+
+ public function testStandardTable() {
+
+ $instance = new HtmlTableRenderer();
+
+ $instance
+ ->addCell( 'lala', [ 'rel' => 'tuuu' ] )
+ ->addRow( [ 'class' => 'foo' ] );
+
+ $this->stringValidator->assertThatStringContains(
+ '<table><tr class="foo row-odd"><td rel="tuuu">lala</td></tr></table>',
+ $instance->getHtml()
+ );
+
+ $instance = new HtmlTableRenderer();
+
+ $instance
+ ->addHeader( 'lula' )
+ ->addCell( 'lala' )
+ ->addRow();
+
+ $this->stringValidator->assertThatStringContains(
+ '<table><th>lula</th><tr class="row-odd"><td>lala</td></tr></table>',
+ $instance->getHtml()
+ );
+
+ $instance = new HtmlTableRenderer( true );
+
+ $instance
+ ->addHeader( 'lula' )
+ ->addCell( 'lala' )
+ ->addRow();
+
+ $this->stringValidator->assertThatStringContains(
+ '<table><thead><th>lula</th></thead><tbody><tr class="row-odd"><td>lala</td></tr></tbody></table>',
+ $instance->getHtml()
+ );
+ }
+
+ public function testTransposedTable() {
+
+ $instance = new HtmlTableRenderer();
+
+ // We need a dedicated header definition to support a table transpose
+ $instance
+ ->transpose( true )
+ ->addHeader( 'Foo' )->addHeader( 'Bar' )
+ ->addCell( 'lala', [ 'class' => 'foo' ] )
+ ->addRow()
+ ->addCell( 'lula', [ 'rel' => 'tuuu' ] )->addCell( 'lila' )
+ ->addRow();
+
+ $this->stringValidator->assertThatStringContains(
+ '<table data-transpose="1"><tr class="row-odd"><th>Foo</th><td class="foo">lala</td><td rel="tuuu">lula</td></tr><tr class="row-even"><th>Bar</th><td></td><td>lila</td></tr></table>',
+ $instance->getHtml()
+ );
+
+ $instance = new HtmlTableRenderer( true );
+
+ $instance
+ ->transpose( true )
+ ->addHeader( 'Foo' )->addHeader( 'Bar' )
+ ->addCell( 'lala', [ 'class' => 'foo' ] )
+ ->addRow()
+ ->addCell( 'lula' )->addCell( 'lila' )
+ ->addRow();
+
+ $this->stringValidator->assertThatStringContains( // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.Files.LineLength
+ '<table data-transpose="1"><thead></thead><tbody><tr class="row-odd"><th>Foo</th><td class="foo">lala</td><td>lula</td></tr><tr class="row-even"><th>Bar</th><td></td><td>lila</td></tr></tbody></table>', // @codingStandardsIgnoreEnd
+ $instance->getHtml()
+ );
+ }
+
+ public function testEmptyTable() {
+
+ $instance = new HtmlTableRenderer();
+
+ $instance
+ ->addCell()
+ ->addRow();
+
+ $this->assertEmpty(
+ $instance->getHtml()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTemplateRendererTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTemplateRendererTest.php
new file mode 100644
index 00000000..0b355066
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/HtmlTemplateRendererTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Renderer;
+
+use SMW\MediaWiki\Renderer\HtmlTemplateRenderer;
+use SMW\MediaWiki\Renderer\WikitextTemplateRenderer;
+
+/**
+ * @covers \SMW\MediaWiki\Renderer\HtmlTemplateRenderer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class HtmlTemplateRendererTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $wikitextTemplateRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\WikitextTemplateRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\HtmlTemplateRenderer',
+ new HtmlTemplateRenderer( $wikitextTemplateRenderer, $parser )
+ );
+ }
+
+ public function testRenderTemplate() {
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parser->expects( $this->once() )
+ ->method( 'recursiveTagParse' )
+ ->with(
+ $this->stringContains( "{{Bar\n|property=Foo\n|value=42}}{{Foobaz\n|property=Bar\n|value=Foo}}" ) );
+
+ $instance = new HtmlTemplateRenderer(
+ new WikitextTemplateRenderer(),
+ $parser
+ );
+
+ $this->assertEmpty(
+ $instance->render()
+ );
+
+ $instance->addField( 'property', 'Foo' );
+ $instance->addField( 'value', 42 );
+
+ $instance->packFieldsForTemplate( 'Bar' );
+
+ $instance->addField( 'property', 'Bar' );
+ $instance->addField( 'value', 'Foo' );
+
+ $instance->packFieldsForTemplate( 'Foobaz' );
+
+ $instance->render();
+
+ $this->assertEmpty(
+ $instance->render()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/WikitextTemplateRendererTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/WikitextTemplateRendererTest.php
new file mode 100644
index 00000000..e4f1d4be
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Renderer/WikitextTemplateRendererTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Renderer;
+
+use SMW\MediaWiki\Renderer\WikitextTemplateRenderer;
+
+/**
+ * @covers \SMW\MediaWiki\Renderer\WikitextTemplateRenderer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class WikitextTemplateRendererTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Renderer\WikitextTemplateRenderer',
+ new WikitextTemplateRenderer()
+ );
+ }
+
+ public function testRenderTemplate() {
+
+ $instance = new WikitextTemplateRenderer();
+
+ $this->assertEmpty(
+ $instance->render()
+ );
+
+ $instance->addField( 'property', 'Foo' );
+ $instance->addField( 'value', 42 );
+
+ $instance->packFieldsForTemplate( 'Bar' );
+
+ $instance->addField( 'property', 'Bar' );
+ $instance->addField( 'value', 'Foo' );
+
+ $instance->packFieldsForTemplate( 'Foobaz' );
+
+ $this->assertEquals(
+ "{{Bar\n|property=Foo\n|value=42}}{{Foobaz\n|property=Bar\n|value=Foo}}",
+ $instance->render()
+ );
+
+ $this->assertEmpty(
+ $instance->render()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/CustomFormTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/CustomFormTest.php
new file mode 100644
index 00000000..042d184b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/CustomFormTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\MediaWiki\Search\Form\CustomForm;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\CustomForm
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CustomFormTest extends \PHPUnit_Framework_TestCase {
+
+ private $webRequest;
+
+ protected function setUp() {
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CustomForm::class,
+ new CustomForm( $this->webRequest )
+ );
+ }
+
+ public function testMakeFields() {
+
+ $this->webRequest->expects( $this->at( 0 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'barproperty' ) )
+ ->will( $this->returnValue( [ 1001 ] ) );
+
+ $instance = new CustomForm(
+ $this->webRequest
+ );
+
+ $instance->isActiveForm( true );
+
+ $form = [
+ '<div class="smw-input-field" style="display:inline-block;">',
+ '<input class="smw-input" name="barproperty[]" value="1001" placeholder="Bar property ..." ',
+ 'data-property="Bar property" title="Bar property"/></div>'
+ ];
+
+ $this->assertContains(
+ implode( '', $form ),
+ $instance->makeFields( [ 'Bar property'] )
+ );
+
+ $this->assertEquals(
+ [
+ 'barproperty' => 1001
+ ],
+ $instance->getParameters()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FieldTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FieldTest.php
new file mode 100644
index 00000000..0a91b60d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FieldTest.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\MediaWiki\Search\Form\Field;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\Field
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FieldTest extends \PHPUnit_Framework_TestCase {
+
+ public function testTooltip() {
+
+ $instance = new Field();
+
+ $this->assertContains(
+ 'Foo ... bar',
+ $instance->tooltip( [ 'tooltip' => 'Foo ... bar' ] )
+ );
+ }
+
+ public function testCreate() {
+
+ $instance = new Field();
+
+ $this->assertContains(
+ 'smw-input-field',
+ $instance->create( 'input', [] )
+ );
+
+ $this->assertContains(
+ 'smw-select',
+ $instance->create( 'select', [] )
+ );
+ }
+
+ public function testSelect() {
+
+ $instance = new Field();
+
+ $attr = [
+ 'list' => [
+ 'A' => 'Foo',
+ 'B' => [ 42, 'disabled' ]
+ ],
+ 'name' => 'Foobar'
+ ];
+
+ $html = $instance->select( $attr );
+
+ $this->assertContains(
+ '<select name="Foobar">',
+ $html
+ );
+
+ $this->assertContains(
+ "<option value='A'>Foo</option>",
+ $html
+ );
+
+ $this->assertContains(
+ "<option value='B' disabled>42</option>",
+ $html
+ );
+ }
+
+ /**
+ * @dataProvider inputAttributeProvider
+ */
+ public function testInput( $attr, $expected ) {
+
+ $instance = new Field();
+
+ $this->assertContains(
+ $expected,
+ $instance->input( $attr )
+ );
+ }
+
+ public function inputAttributeProvider() {
+
+ yield [
+ [ 'name' => 'Foobar' ],
+ '<div class="smw-input-field"><input name="Foobar" placeholder=""/></div>'
+ ];
+
+ yield [
+ [ 'name' => 'Foobar', 'multifield' => true ],
+ '<div class="smw-input-field"><input name="Foobar[]" placeholder=""/></div>'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsBuilderTest.php
new file mode 100644
index 00000000..f7db2ae3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsBuilderTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\MediaWiki\Search\Form\FormsBuilder;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\FormsBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FormsBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $webRequest;
+ private $formsFactory;
+
+ protected function setUp() {
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->formsFactory = $this->getMockBuilder( '\SMW\MediaWiki\Search\Form\FormsFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FormsBuilder::class,
+ new FormsBuilder( $this->webRequest, $this->formsFactory )
+ );
+ }
+
+ public function testBuildForm() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $openForm = $this->getMockBuilder( '\SMW\MediaWiki\Search\Form\OpenForm' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $customForm = $this->getMockBuilder( '\SMW\MediaWiki\Search\Form\CustomForm' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $customForm->expects( $this->any() )
+ ->method( 'getParameters' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->formsFactory->expects( $this->any() )
+ ->method( 'newOpenForm' )
+ ->will( $this->returnValue( $openForm ) );
+
+ $this->formsFactory->expects( $this->any() )
+ ->method( 'newCustomForm' )
+ ->will( $this->returnValue( $customForm ) );
+
+ $instance = new FormsBuilder(
+ $this->webRequest,
+ $this->formsFactory
+ );
+
+ $data = [
+ 'forms' => [
+ 'Foo' => [
+ 'Property one'
+ ],
+ 'Bar' => [
+ 'Property two'
+ ]
+ ]
+ ];
+
+ $expected = [
+ "<div class='divider' style='display:none;'></div>",
+ '<div id="smw-form-definitions" class="is-disabled">',
+ '<div id="smw-form-bar" class="smw-fields"></div>',
+ '<div id="smw-form-foo" class="smw-fields"></div></div>'
+ ];
+
+ $this->assertContains(
+ implode( '', $expected ),
+ $instance->buildForm( $data )
+ );
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $expected = [
+ '<button type="button" id="smw-search-forms" class="smw-selectmenu-button is-disabled".*',
+ 'name="smw-form" value="".*',
+ 'data-list="[{&quot;id&quot;:&quot;bar&quot;,&quot;name&quot;:&quot;Bar&quot;,&quot;desc&quot;:&quot;Bar&quot;},{&quot;id&quot;:&quot;foo&quot;,&quot;name&quot;:&quot;Foo&quot;,&quot;desc&quot;:&quot;Foo&quot;}]" data-nslist="[]">Form</button><input type="hidden" name="smw-form"/>'
+ ];
+
+ $stringValidator->assertThatStringContains(
+ $expected,
+ $instance->buildFormList( $title )
+ );
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFactoryTest.php
new file mode 100644
index 00000000..a5fc0026
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFactoryTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\MediaWiki\Search\Form\FormsFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\FormsFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FormsFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $webRequest;
+
+ protected function setUp() {
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FormsFactory::class,
+ new FormsFactory()
+ );
+ }
+
+ public function testCanConstructOpenForm() {
+
+ $instance = new FormsFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Search\Form\OpenForm',
+ $instance->newOpenForm( $this->webRequest )
+ );
+ }
+
+ public function testCanConstructCustomForm() {
+
+ $instance = new FormsFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Search\Form\CustomForm',
+ $instance->newCustomForm( $this->webRequest )
+ );
+ }
+
+ public function testCanConstructSortForm() {
+
+ $instance = new FormsFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Search\Form\SortForm',
+ $instance->newSortForm( $this->webRequest )
+ );
+ }
+
+ public function testCanConstructNamespaceForm() {
+
+ $instance = new FormsFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Search\Form\NamespaceForm',
+ $instance->newNamespaceForm()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFinderTest.php
new file mode 100644
index 00000000..697c42ba
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/FormsFinderTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Search\Form\FormsFinder;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\FormsFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FormsFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FormsFinder::class,
+ new FormsFinder( $this->store )
+ );
+ }
+
+ public function testGetFormDefinitions() {
+
+ $data[] = json_encode( [ 'Foo' => [ 'Bar' => 42 ], 1001 ] );
+ $data[] = json_encode( [ 'Foo' => [ 'Foobar' => 'test' ], [ 'Foo' => 'Bar' ] ] );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ) ] ) );
+
+ $instance = $this->getMockBuilder( '\SMW\MediaWiki\Search\Form\FormsFinder' )
+ ->setConstructorArgs( [ $this->store ] )
+ ->setMethods( [ 'getNativeData' ] )
+ ->getMock();
+
+ $instance->expects( $this->any() )
+ ->method( 'getNativeData' )
+ ->will( $this->onConsecutiveCalls( $data[0], $data[1] ) );
+
+ $this->assertEquals(
+ [
+ 'Foo' => [ 'Bar' => 42, 'Foobar' => 'test' ],
+ 1001,
+ [ 'Foo' => 'Bar' ]
+ ],
+ $instance->getFormDefinitions()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/NamespaceFormTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/NamespaceFormTest.php
new file mode 100644
index 00000000..6608de21
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/NamespaceFormTest.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\MediaWiki\Search\Form\NamespaceForm;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\NamespaceForm
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class NamespaceFormTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ NamespaceForm::class,
+ new NamespaceForm()
+ );
+ }
+
+ public function testMakeFields() {
+
+ $instance = new NamespaceForm();
+
+ $instance->setSearchableNamespaces( [ 0 => 'Foo '] );
+
+ $this->assertContains(
+ "<fieldset id='mw-searchoptions'>",
+ $instance->makeFields()
+ );
+ }
+
+ public function testCheckNamespaceEditToken() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'getEditToken' );
+
+ $user->expects( $this->any() )
+ ->method( 'isLoggedIn' )
+ ->will( $this->returnValue( true ) );
+
+ $specialSearch = $this->getMockBuilder( '\SpecialSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $specialSearch->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $user ) );
+
+ $instance = new NamespaceForm();
+
+ $instance->checkNamespaceEditToken( $specialSearch );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/OpenFormTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/OpenFormTest.php
new file mode 100644
index 00000000..fea0b999
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/OpenFormTest.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\MediaWiki\Search\Form\OpenForm;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\OpenForm
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class OpenFormTest extends \PHPUnit_Framework_TestCase {
+
+ private $webRequest;
+
+ protected function setUp() {
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ OpenForm::class,
+ new OpenForm( $this->webRequest )
+ );
+ }
+
+ public function testMakeFields() {
+
+ $this->webRequest->expects( $this->at( 0 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'property' ) )
+ ->will( $this->returnValue( [ 'Bar' ] ) );
+
+ $this->webRequest->expects( $this->at( 1 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'pvalue' ) )
+ ->will( $this->returnValue( [ 42 ] ) );
+
+ $this->webRequest->expects( $this->at( 2 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'op' ) )
+ ->will( $this->returnValue( [ 'OR' ] ) );
+
+ $instance = new OpenForm(
+ $this->webRequest
+ );
+
+ $instance->isActiveForm( true );
+
+ $this->assertContains(
+ '<div class="smw-input-group"><div class="smw-input-field" style="display:inline-block;">',
+ $instance->makeFields( [] )
+ );
+
+ $this->assertEquals(
+ [
+ 'property' => [ 'Bar' ],
+ 'pvalue' => [ 42 ],
+ 'op' => [ 'OR' ]
+ ],
+ $instance->getParameters()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/SortFormTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/SortFormTest.php
new file mode 100644
index 00000000..4040e1a9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/Form/SortFormTest.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search\Form;
+
+use SMW\MediaWiki\Search\Form\SortForm;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Form\SortForm
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SortFormTest extends \PHPUnit_Framework_TestCase {
+
+ private $webRequest;
+
+ protected function setUp() {
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SortForm::class,
+ new SortForm( $this->webRequest )
+ );
+ }
+
+ public function testMakeFields() {
+
+ $this->webRequest->expects( $this->at( 0 ) )
+ ->method( 'getVal' )
+ ->with( $this->equalTo( 'sort' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new SortForm(
+ $this->webRequest
+ );
+
+ $this->assertContains(
+ 'smw-search-sort',
+ $instance->makeFields( [] )
+ );
+
+ $this->assertEquals(
+ [ 'sort' => 'Foo' ],
+ $instance->getParameters()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/QueryBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/QueryBuilderTest.php
new file mode 100644
index 00000000..8904c47f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/QueryBuilderTest.php
@@ -0,0 +1,224 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search;
+
+use SMW\MediaWiki\Search\QueryBuilder;
+
+/**
+ * @covers \SMW\MediaWiki\Search\QueryBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class QueryBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $webRequest;
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ QueryBuilder::class,
+ new QueryBuilder( $this->webRequest )
+ );
+ }
+
+ public function testGetQuery() {
+
+ $instance = new QueryBuilder(
+ $this->webRequest
+ );
+
+ $this->assertNull(
+ $instance->getQuery( 'Foo' )
+ );
+
+ $this->assertInstanceOf(
+ '\SMWQuery',
+ $instance->getQuery( '[[Foo::bar]]' )
+ );
+ }
+
+ public function testAddNamespaceCondition() {
+
+ $this->webRequest->expects( $this->any() )
+ ->method( 'getCheck' )
+ ->with($this->equalTo( 'ns6' ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new QueryBuilder(
+ $this->webRequest
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ThingDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $query->expects( $this->once() )
+ ->method( 'setDescription' );
+
+ $instance->addNamespaceCondition( $query, [ 6 => true ] );
+ }
+
+ public function testAddSort() {
+
+ $this->webRequest->expects( $this->any() )
+ ->method( 'getVal' )
+ ->with($this->equalTo( 'sort' ) )
+ ->will( $this->returnValue( 'recent' ) );
+
+ $instance = new QueryBuilder(
+ $this->webRequest
+ );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'setSortKeys' );
+
+ $instance->addSort( $query );
+ }
+
+ public function testGetQueryString_EmptyFieldValues_ReturnsTermOnly() {
+
+ $instance = new QueryBuilder(
+ $this->webRequest,
+ [ 'foo' ]
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getQueryString( $this->store, 'Foo' )
+ );
+ }
+
+ public function testGetQueryString_FormFieldValues() {
+
+ $form_def = [
+ 'forms' => [
+ 'Foo' => [
+ 'Bar property'
+ ]
+ ]
+ ];
+
+ $this->webRequest->expects( $this->at( 0 ) )
+ ->method( 'getVal' )
+ ->with( $this->equalTo( 'smw-form' ) )
+ ->will( $this->returnValue( 'foo' ) );
+
+ $this->webRequest->expects( $this->at( 1 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'barproperty' ) )
+ ->will( $this->returnValue( [ 'Foobar' ] ) );
+
+ $instance = new QueryBuilder(
+ $this->webRequest,
+ $form_def
+ );
+
+ $this->assertEquals(
+ '<q>[[Bar property::Foobar]]</q> Foo',
+ $instance->getQueryString( $this->store, 'Foo' )
+ );
+ }
+
+ public function testGetQueryString_DifferentFormsFieldValues() {
+
+ $form_def = [
+ 'forms' => [
+ 'Foo-1' => [
+ 'Bar property'
+ ],
+ 'Foo-2' => [
+ 'Bar property'
+ ]
+ ]
+ ];
+
+ $this->webRequest->expects( $this->at( 0 ) )
+ ->method( 'getVal' )
+ ->with( $this->equalTo( 'smw-form' ) )
+ ->will( $this->returnValue( 'foo-2' ) );
+
+ $this->webRequest->expects( $this->at( 1 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'barproperty' ) )
+ ->will( $this->returnValue( [ '', 42 ] ) );
+
+ $instance = new QueryBuilder(
+ $this->webRequest,
+ $form_def
+ );
+
+ $this->assertEquals(
+ '<q>[[Bar property::42]]</q> Foo',
+ $instance->getQueryString( $this->store, 'Foo' )
+ );
+ }
+
+ public function testGetQueryString_OpenFormFieldValues() {
+
+ $form_def = [
+ 'forms' => [
+ 'open'
+ ]
+ ];
+
+ $this->webRequest->expects( $this->at( 0 ) )
+ ->method( 'getVal' )
+ ->with( $this->equalTo( 'smw-form' ) )
+ ->will( $this->returnValue( 'open' ) );
+
+ $this->webRequest->expects( $this->at( 1 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'property' ) )
+ ->will( $this->returnValue( [ 'Bar' ] ) );
+
+ $this->webRequest->expects( $this->at( 2 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'pvalue' ) )
+ ->will( $this->returnValue( [ 42 ] ) );
+
+ $this->webRequest->expects( $this->at( 3 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'op' ) )
+ ->will( $this->returnValue( [ 'OR' ] ) );
+
+ $instance = new QueryBuilder(
+ $this->webRequest,
+ $form_def
+ );
+
+ $this->assertEquals(
+ '<q>[[Bar::42]] </q> OR Foo',
+ $instance->getQueryString( $this->store, 'Foo' )
+ );
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchProfileFormTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchProfileFormTest.php
new file mode 100644
index 00000000..0cd521c9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchProfileFormTest.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search;
+
+use SMW\MediaWiki\Search\SearchProfileForm;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Search\SearchProfileForm
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SearchProfileFormTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $specialSearch;
+ private $requestContext;
+ private $outputPage;
+ private $webRequest;
+ private $user;
+ private $stringValidator;
+
+ protected function setUp() {
+
+ $this->stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->specialSearch = $this->getMockBuilder( '\SpecialSearch' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestContext = $this->getMockBuilder( '\RequestContext' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestContext->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->outputPage ) );
+
+ $this->requestContext->expects( $this->any() )
+ ->method( 'getRequest' )
+ ->will( $this->returnValue( $this->webRequest ) );
+
+ $this->requestContext->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $this->user ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SearchProfileForm::class,
+ new SearchProfileForm( $this->store, $this->specialSearch )
+ );
+ }
+
+ public function testAddProfile() {
+
+ $profile = [];
+
+ SearchProfileForm::addProfile( 'SMWSearch', $profile );
+
+ $this->assertArrayHasKey(
+ 'smw',
+ $profile
+ );
+ }
+
+ public function testGetForm() {
+
+ $form = '';
+ $opts = [];
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $searchEngine = $this->getMockBuilder( '\SMW\MediaWiki\Search\Search' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->specialSearch->expects( $this->any() )
+ ->method( 'getSearchEngine' )
+ ->will( $this->returnValue( $searchEngine ) );
+
+ $this->specialSearch->expects( $this->any() )
+ ->method( 'getNamespaces' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->specialSearch->expects( $this->any() )
+ ->method( 'getUser' )
+ ->will( $this->returnValue( $this->user ) );
+
+ $this->specialSearch->expects( $this->any() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $this->requestContext ) );
+
+ $instance = new SearchProfileForm(
+ $this->store,
+ $this->specialSearch
+ );
+
+ $instance->getForm( $form, $opts );
+
+ $expected = [
+ '<fieldset id="smw-searchoptions">',
+ '<input type="hidden" name="ns-list"/>',
+ '<div class="smw-search-options">',
+ '<div class="smw-search-sort"><button type="button" id="smw-search-sort" class="smw-selectmenu-button is-disabled" name="sort"',
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $form
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultSetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultSetTest.php
new file mode 100644
index 00000000..997193c0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultSetTest.php
@@ -0,0 +1,222 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search;
+
+use SMW\MediaWiki\Search\SearchResultSet;
+
+/**
+ * @covers \SMW\MediaWiki\Search\SearchResultSet
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author Stephan Gambke
+ */
+class SearchResultSetTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var SearchResultSet The search result set under test
+ */
+ protected $resultSet;
+ private $queryResult;
+
+ protected function setUp() {
+
+ $queryToken = $this->getMockBuilder( '\SMW\Query\QueryToken' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryToken->expects( $this->any() )
+ ->method( 'getTokens' )
+ ->will( $this->returnValue( [] ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryToken' )
+ ->will( $this->returnValue( $queryToken ) );
+
+ $this->queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getQuery', 'getResults' ] )
+ ->getMock();
+
+ $pageMock = $this->getMockBuilder( 'SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageMock->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( null ) );
+
+ $this->queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $this->queryResult->expects( $this->any() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [ $pageMock, $pageMock, $pageMock ] ) );
+
+ $this->resultSet = new SearchResultSet( $this->queryResult, 42 );
+
+ }
+
+ public function testCanConstruct() {
+ $this->assertInstanceOf( '\SMW\MediaWiki\Search\SearchResultSet', $this->resultSet );
+ }
+
+ public function testNumRows() {
+ $this->assertEquals( 3, $this->resultSet->numRows() );
+ }
+
+ public function testHasResults() {
+ $this->assertGreaterThan( 0, $this->resultSet->hasResults() );
+ }
+
+ public function testNext() {
+ $this->assertInstanceOf( 'SearchResult', $this->resultSet->next() );
+ $this->assertInstanceOf( 'SearchResult', $this->resultSet->next() );
+ $this->assertInstanceOf( 'SearchResult', $this->resultSet->next() );
+ $this->assertFalse( $this->resultSet->next() );
+ }
+
+ public function testExtractResults() {
+
+ $res = $this->resultSet->extractResults();
+
+ $this->assertCount(
+ 3,
+ $res
+ );
+
+ $this->assertEquals(
+ 3,
+ $this->resultSet->numRows()
+ );
+
+ foreach ( $res as $searchResult ) {
+ $this->assertInstanceOf(
+ 'SearchResult',
+ $searchResult
+ );
+ }
+ }
+
+ public function testSearchContainedSyntax() {
+ $this->assertTrue( $this->resultSet->searchContainedSyntax() );
+ }
+
+ public function testGetTotalHits() {
+ $this->assertEquals( 42, $this->resultSet->getTotalHits() );
+ }
+
+ public function testExcerpt() {
+
+ $excerpts = $this->getMockBuilder( 'SMW\Query\Excerpts' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $excerpts->expects( $this->any() )
+ ->method( 'getExcerpt' )
+ ->will( $this->returnValue( 'Foo ...' ) );
+
+ $this->queryResult->setExcerpts( $excerpts );
+
+ $resultSet = new SearchResultSet( $this->queryResult, 42 );
+ $searchResult = $resultSet->next();
+
+ $this->assertEquals(
+ 'Foo ...',
+ $searchResult->getExcerpt()
+ );
+ }
+
+ public function testTermMatches() {
+
+ $queryToken = $this->getMockBuilder( '\SMW\Query\QueryToken' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryToken->expects( $this->any() )
+ ->method( 'getTokens' )
+ ->will( $this->returnValue( [ 'Foo' => 1, 'Bar' => 2 ] ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryToken' )
+ ->will( $this->returnValue( $queryToken ) );
+
+ $queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getQuery', 'getResults' ] )
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $resultSet = new SearchResultSet( $queryResult, 42 );
+
+ $this->assertEquals(
+ [ '\bFoo\b', '\bBar\b' ],
+ $resultSet->termMatches()
+ );
+ }
+
+ public function testNewSearchSuggestionSet() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $page = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $page->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $queryToken = $this->getMockBuilder( '\SMW\Query\QueryToken' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryToken' )
+ ->will( $this->returnValue( $queryToken ) );
+
+ $queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [ $page ] ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $resultSet = new SearchResultSet( $queryResult, 42 );
+
+ $this->assertInstanceOf(
+ '\SearchSuggestionSet',
+ $resultSet->newSearchSuggestionSet()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultTest.php
new file mode 100644
index 00000000..71649410
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchResultTest.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search;
+
+use SMW\MediaWiki\Search\SearchResult;
+
+/**
+ * @covers \SMW\MediaWiki\Search\SearchResult
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SearchResultTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGetSectionTitle_WithFragment() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getFragment' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = SearchResult::newFromTitle( $title );
+
+ $this->assertInstanceOf(
+ '\Title',
+ $instance->getSectionTitle()
+ );
+ }
+
+ public function testGetSectionTitle_WithoutFragment() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getFragment' )
+ ->will( $this->returnValue( '' ) );
+
+ $instance = SearchResult::newFromTitle( $title );
+
+ $this->assertNull(
+ $instance->getSectionTitle()
+ );
+ }
+
+ public function testExcerpt() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getFragment' )
+ ->will( $this->returnValue( '' ) );
+
+ $instance = SearchResult::newFromTitle( $title );
+ $instance->setExcerpt( 'Foo ...' );
+
+ $this->assertEquals(
+ 'Foo ...',
+ $instance->getExcerpt()
+ );
+ }
+
+ public function testGetTitleSnippet() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getFragment' )
+ ->will( $this->returnValue( '' ) );
+
+ $instance = SearchResult::newFromTitle( $title );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getTitleSnippet()
+ );
+ }
+
+ public function testGetTextSnippet_HasHighlight() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = SearchResult::newFromTitle( $title );
+
+ $instance->setExcerpt( '<em>Foo</em>bar', true );
+
+ $this->assertEquals(
+ "<span class='searchmatch'>Foo</span>bar",
+ $instance->getTextSnippet( [ 'Foo' ] )
+ );
+ }
+
+ public function testGetTextSnippet_NoHighlight() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = SearchResult::newFromTitle( $title );
+
+ $instance->setExcerpt( 'Foobar' );
+
+ $this->assertEquals(
+ "<span class='searchmatch'>Foo</span>bar\n",
+ $instance->getTextSnippet( [ 'Foo' ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchTest.php
new file mode 100644
index 00000000..840cae3a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Search/SearchTest.php
@@ -0,0 +1,635 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Search;
+
+use SMW\MediaWiki\Search\Search;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+use SMWQuery;
+
+/**
+ * @covers \SMW\MediaWiki\Search\Search
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author Stephan Gambke
+ */
+class SearchTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Search\Search',
+ new Search()
+ );
+ }
+
+ public function testGetDefaultDBConnection() {
+
+ $search = new Search();
+
+ $this->assertInstanceOf(
+ 'DatabaseBase',
+ $search->getDB()
+ );
+ }
+
+ public function testSetGetDBConnection() {
+
+ $dbMock = $this->getMockBuilder( 'DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $search = new Search();
+ $search->setDB( $dbMock );
+
+ $this->assertEquals( $dbMock, $search->getDB() );
+ }
+
+ public function testGetDefaultFallbackSearchEngineForNullFallbackSearchType() {
+
+ $searchEngine = 'SearchDatabase';
+
+ if ( class_exists( 'SearchEngine' ) ) {
+
+ $reflection = new \ReflectionClass( 'SearchEngine' );
+
+ if ( $reflection->isInstantiable() ) {
+ $searchEngine = 'SearchEngine';
+ }
+ }
+
+ $databaseBase = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSearchEngine' ] )
+ ->getMockForAbstractClass();
+
+ $databaseBase->expects( $this->any() )
+ ->method( 'getSearchEngine' )
+ ->will( $this->returnValue( $searchEngine ) );
+
+ $this->testEnvironment->addConfiguration( 'smwgFallbackSearchType', null );
+
+ $search = new Search();
+ $search->setDB( $databaseBase );
+
+ $this->assertInstanceOf(
+ 'SearchEngine',
+ $search->getFallbackSearchEngine()
+ );
+ }
+
+ public function testInvalidFallbackSearchEngineThrowsException() {
+
+ $this->testEnvironment->addConfiguration( 'smwgFallbackSearchType', 'InvalidFallbackSearchEngine' );
+
+ $search = new Search();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $search->getFallbackSearchEngine();
+ }
+
+ public function testSetGetFallbackSearchEngine() {
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertEquals(
+ $searchEngine,
+ $search->getFallbackSearchEngine()
+ );
+ }
+
+ public function testSearchTitle_withNonsemanticQuery() {
+
+ $term = 'Some string that can not be interpreted as a semantic query';
+
+ $searchResultSet = $this->getMockBuilder( 'SearchResultSet' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'transformSearchTerm' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'replacePrefixes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'searchTitle')
+ ->will( $this->returnValueMap( [ [ $term, $searchResultSet ] ] ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertEquals(
+ $searchResultSet,
+ $search->searchTitle( $term )
+ );
+ }
+
+ public function testSearchTitle_withEmptyQuery() {
+
+ $term = ' ';
+
+ $searchResultSet = $this->getMockBuilder( 'SearchResultSet' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'transformSearchTerm' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'replacePrefixes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'searchTitle')
+ ->will( $this->returnValueMap( [ [ $term, $searchResultSet ] ] ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertEquals(
+ $searchResultSet,
+ $search->searchTitle( $term )
+ );
+ }
+
+ public function testSearchText_withSemanticQuery() {
+
+ $term = '[[Some string that can be interpreted as a semantic query]]';
+
+ $infoLink = $this->getMockBuilder( '\SMWInfolink' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQueryLink' )
+ ->will( $this->returnValue( $infoLink ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->exactly( 2 ) )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnCallback( function ( SMWQuery $query ) use ( $queryResult ) {
+ return $query->querymode === SMWQuery::MODE_COUNT ? 9001 : $queryResult;
+ } ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $search = new Search();
+ $result = $search->searchText( $term );
+
+ $this->assertInstanceOf(
+ 'SMW\MediaWiki\Search\SearchResultSet',
+ $result
+ );
+
+ $this->assertEquals(
+ 9001,
+ $result->getTotalHits()
+ );
+ }
+
+ public function testSearchText_withNonsemanticQuery() {
+
+ $term = 'Some string that can not be interpreted as a semantic query';
+
+ $searchResultSet = $this->getMockBuilder( 'SearchResultSet' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'transformSearchTerm' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'replacePrefixes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'searchText')
+ ->will( $this->returnValueMap( [ [ $term, $searchResultSet ] ] ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertEquals(
+ $searchResultSet,
+ $search->searchText( $term )
+ );
+ }
+
+ public function testSearchTitle_withSemanticQuery() {
+
+ $term = '[[Some string that can be interpreted as a semantic query]]';
+
+ $search = new Search();
+
+ $this->assertNull( $search->searchTitle( $term ) );
+ }
+
+ public function testSupports() {
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'supports')
+ ->with( $this->equalTo( 'Some feature' ) )
+ ->will( $this->returnValueMap( [ [ 'Some feature', true ] ] ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertTrue( $search->supports( 'Some feature' ) );
+ }
+
+ public function testNormalizeText() {
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'normalizeText')
+ ->with( $this->equalTo( 'Some text' ) )
+ ->will( $this->returnValueMap( [ [ 'Some text', 'Some normalized text' ] ] ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertEquals(
+ 'Some normalized text',
+ $search->normalizeText( 'Some text' )
+ );
+ }
+
+ public function testGetTextFromContent() {
+
+ if ( ! method_exists( 'SearchEngine', 'getTextFromContent' ) ) {
+ $this->markTestSkipped( 'SearchEngine::getTextFromContent() is undefined. Probably not yet present in the tested MW version.' );
+ }
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $content = $this->getMockBuilder( 'Content' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'getTextFromContent')
+ ->with(
+ $this->equalTo( $title ),
+ $this->equalTo( $content ) )
+ ->will( $this->returnValueMap( [ [ $title, $content, 'text from content for title' ] ] ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertEquals(
+ 'text from content for title',
+ $search->getTextFromContent( $title, $content )
+ );
+ }
+
+
+ public function testTextAlreadyUpdatedForIndex() {
+
+ if ( ! method_exists( 'SearchEngine', 'textAlreadyUpdatedForIndex' ) ) {
+ $this->markTestSkipped( 'SearchEngine::textAlreadyUpdatedForIndex() is undefined. Probably not yet present in the tested MW version.' );
+ }
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'textAlreadyUpdatedForIndex')
+ ->with()
+ ->will( $this->returnValue( true ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertTrue( $search->textAlreadyUpdatedForIndex( 'Some text' ) );
+ }
+
+ public function testUpdate() {
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'update')
+ ->with(
+ $this->equalTo( 42 ),
+ $this->equalTo( 'Some title' ),
+ $this->equalTo( 'Some text' ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $search->update( 42, 'Some title', 'Some text' );
+ }
+
+ public function testUpdateTitle() {
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'updateTitle')
+ ->with(
+ $this->equalTo( 42 ),
+ $this->equalTo( 'Some title' ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $search->updateTitle( 42, 'Some title' );
+ }
+
+ public function testDelete() {
+
+ if ( ! method_exists( 'SearchEngine', 'delete' ) ) {
+ $this->markTestSkipped( 'SearchEngine::delete() is undefined. Probably not yet present in the tested MW version.' );
+ }
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'delete')
+ ->with(
+ $this->equalTo( 42 ),
+ $this->equalTo( 'Some title' ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $search->delete( 42, 'Some title' );
+ }
+
+ public function testSetFeatureData() {
+
+ if ( ! method_exists( 'SearchEngine', 'delete' ) ) {
+ $this->markTestSkipped( 'SearchEngine::delete() is undefined. Probably not yet present in the tested MW version.' );
+ }
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'setFeatureData')
+ ->with(
+ $this->equalTo( 'Some feature name' ),
+ $this->equalTo( 'Some feature expression' ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+ $search->setFeatureData( 'Some feature name', 'Some feature expression' );
+
+ $this->assertEquals(
+ 'Some feature expression',
+ $search->getFeatureData( 'Some feature name' )
+ );
+
+ $this->assertNull( $search->getFeatureData( 'Some non-existent feature name' ) );
+ }
+
+ public function testReplacePrefixes() {
+
+ $search = new Search();
+
+ $this->assertEquals(
+ 'Some query',
+ $search->replacePrefixes( 'Some query' )
+ );
+ }
+
+ public function testTransformSearchTerm() {
+
+ $search = new Search();
+
+ $this->assertEquals(
+ 'Some query',
+ $search->transformSearchTerm( 'Some query' )
+ );
+ }
+
+ public function testSetLimitOffset() {
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'setLimitOffset')
+ ->with(
+ $this->equalTo( 9001 ),
+ $this->equalTo( 42 ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $search->setLimitOffset( 9001, 42 );
+
+ $this->assertEquals( 9001, $search->getLimit() );
+ $this->assertEquals( 42, $search->getOffset() );
+ }
+
+ public function testSetNamespaces() {
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'setNamespaces')
+ ->with( $this->equalTo( [ 1, 2, 3, 5, 8 ] ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+ $search->setNamespaces( [ 1, 2, 3, 5, 8 ] );
+
+ $this->assertEquals(
+ [ 1, 2, 3, 5, 8 ],
+ $search->namespaces
+ );
+ }
+
+ public function testSetShowSuggestion() {
+
+ if ( ! method_exists( 'SearchEngine', 'setShowSuggestion' ) ) {
+ $this->markTestSkipped( 'SearchEngine::setShowSuggestion() is undefined. Probably not yet present in the tested MW version.' );
+ }
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'setShowSuggestion')
+ ->with( $this->equalTo( true ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+ $search->setShowSuggestion( true );
+
+ $this->assertTrue( $search->getShowSuggestion() );
+ }
+
+ public function testCompletionSearch_OnEligiblePrefix() {
+
+ $infoLink = $this->getMockBuilder( '\SMWInfolink' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQueryLink' )
+ ->will( $this->returnValue( $infoLink ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+
+ $this->assertInstanceof(
+ '\SearchSuggestionSet',
+ $search->completionSearch( 'in:Foo' )
+ );
+ }
+
+ public function testCompletionSearch_NoRelevantPrefix() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchSuggestionSet = $this->getMockBuilder( '\SearchSuggestionSet' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchSuggestionSet->expects( $this->any() )
+ ->method( 'map')
+ ->will( $this->returnValue( [] ) );
+
+ $searchEngine = $this->getMockBuilder( 'SearchEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'setShowSuggestion')
+ ->with( $this->equalTo( true ) );
+
+ $searchEngine->expects( $this->once() )
+ ->method( 'completionSearch' )
+ ->will( $this->returnValue( $searchSuggestionSet ) );
+
+ $search = new Search();
+ $search->setFallbackSearchEngine( $searchEngine );
+ $search->setShowSuggestion( true );
+
+ $this->assertInstanceof(
+ '\SearchSuggestionSet',
+ $search->completionSearch( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/CacheStatisticsListTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/CacheStatisticsListTaskHandlerTest.php
new file mode 100644
index 00000000..e2f0200a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/CacheStatisticsListTaskHandlerTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\CacheStatisticsListTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\CacheStatisticsListTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CacheStatisticsListTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CacheStatisticsListTaskHandler::class,
+ new CacheStatisticsListTaskHandler( $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new CacheStatisticsListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testIsTaskFor() {
+
+ $instance = new CacheStatisticsListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $this->assertTrue(
+ $instance->isTaskFor( 'stats/cache')
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $this->outputFormatter->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' );
+
+ $instance = new CacheStatisticsListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance->handleRequest( $webRequest );
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/ConfigurationListTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/ConfigurationListTaskHandlerTest.php
new file mode 100644
index 00000000..93242fe8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/ConfigurationListTaskHandlerTest.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\ConfigurationListTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\ConfigurationListTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ConfigurationListTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConfigurationListTaskHandler::class,
+ new ConfigurationListTaskHandler( $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new ConfigurationListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $this->outputFormatter->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' );
+
+ $instance = new ConfigurationListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DataRefreshJobTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DataRefreshJobTaskHandlerTest.php
new file mode 100644
index 00000000..85600d07
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DataRefreshJobTaskHandlerTest.php
@@ -0,0 +1,151 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\DataRefreshJobTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\DataRefreshJobTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DataRefreshJobTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $htmlFormRenderer;
+ private $outputFormatter;
+ private $jobQueue;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $this->jobQueue );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\DataRefreshJobTaskHandler',
+ new DataRefreshJobTaskHandler( $this->htmlFormRenderer, $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addSubmitButton'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new DataRefreshJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->getHtml();
+ }
+
+ public function testDoRefreshOn_Yes() {
+
+ $refreshJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\RefreshJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobQueue->expects( $this->atLeastOnce() )
+ ->method( 'hasPendingJob' )
+ ->with( $this->equalTo( 'SMW\RefreshJob' ) )
+ ->will( $this->returnValue( true ) );
+
+ $this->jobQueue->expects( $this->atLeastOnce() )
+ ->method( 'pop' )
+ ->with( $this->equalTo( 'SMW\RefreshJob' ) )
+ ->will( $this->returnValue( false ) );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->atLeastOnce() )
+ ->method( 'newByType' )
+ ->will( $this->returnValue( $refreshJob ) );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $webRequest->expects( $this->atLeastOnce() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( 'yes' ) );
+
+ $instance = new DataRefreshJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->setEnabledFeatures( SMW_ADM_REFRESH );
+ $instance->handleRequest( $webRequest );
+ }
+
+ public function testDoRefreshOn_Stop() {
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'delete' )
+ ->with( $this->equalTo( 'SMW\RefreshJob' ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $webRequest->expects( $this->atLeastOnce() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( 'stop' ) );
+
+ $instance = new DataRefreshJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->setEnabledFeatures( SMW_ADM_REFRESH );
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DeprecationNoticeTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DeprecationNoticeTaskHandlerTest.php
new file mode 100644
index 00000000..d4c75bf8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DeprecationNoticeTaskHandlerTest.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\DeprecationNoticeTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\DeprecationNoticeTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DeprecationNoticeTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ DeprecationNoticeTaskHandler::class,
+ new DeprecationNoticeTaskHandler( $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new DeprecationNoticeTaskHandler(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testGetHtmlWithFakeDetection() {
+
+ $GLOBALS['deprecationNoticeFoo'] = 'Foo';
+ $GLOBALS['deprecationNoticeFoobar'] = 'Foo';
+ $GLOBALS['deprecationNoticeFooFoo'] = 'Foo';
+
+ $deprecationNotice['smw'] = [
+ 'notice' => [
+ 'deprecationNoticeFoo' => '...',
+ 'options' => [
+ 'deprecationNoticeFoo' => [
+ 'Foo',
+ 'Bar'
+ ]
+ ]
+ ],
+ 'replacement' => [
+ 'deprecationNoticeFoobar' => '...',
+ 'options' => [
+ 'deprecationNoticeFoobar' => [
+ 'Foo',
+ 'Bar'
+ ]
+ ]
+ ],
+ 'removal' => [
+ 'deprecationNoticeFooFoo' => '...'
+ ]
+ ];
+
+ $instance = new DeprecationNoticeTaskHandler(
+ $this->outputFormatter,
+ $deprecationNotice
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testGetHtmlWithFakeDetectionArray() {
+
+ $GLOBALS['deprecationNoticeFoo'] = [ 'Bar' => false ];
+ $GLOBALS['deprecationNoticeFoobar'] = 'Foo';
+ $GLOBALS['deprecationNoticeFooFoo'] = 'Foo';
+
+ $deprecationNotice['smw'] = [
+ 'notice' => [
+ 'deprecationNoticeFoo' => '...',
+ 'options' => [
+ 'deprecationNoticeFoo' => [
+ 'Foo',
+ 'Bar'
+ ]
+ ]
+ ],
+ 'replacement' => [
+ 'deprecationNoticeFoobar' => '...',
+ 'options' => [
+ 'deprecationNoticeFoobar' => [
+ 'Foo',
+ 'Bar'
+ ]
+ ]
+ ],
+ 'removal' => [
+ 'deprecationNoticeFooFoo' => '...'
+ ]
+ ];
+
+ $instance = new DeprecationNoticeTaskHandler(
+ $this->outputFormatter,
+ $deprecationNotice
+ );
+
+ $this->assertContains(
+ '<div class="smw-admin-deprecation">',
+ $instance->getHtml()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DisposeJobTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DisposeJobTaskHandlerTest.php
new file mode 100644
index 00000000..de961220
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DisposeJobTaskHandlerTest.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\DisposeJobTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\DisposeJobTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DisposeJobTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $htmlFormRenderer;
+ private $outputFormatter;
+ private $jobQueue;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $this->jobQueue );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\DisposeJobTaskHandler',
+ new DisposeJobTaskHandler( $this->htmlFormRenderer, $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addSubmitButton'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new DisposeJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->getHtml();
+ }
+
+ public function testHandleRequestOnNonPendingJob() {
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'hasPendingJob' )
+ ->with( $this->equalTo( 'smw.entityIdDisposer' ) )
+ ->will( $this->returnValue( false ) );
+
+ $entityIdDisposerJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\EntityIdDisposerJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityIdDisposerJob->expects( $this->once() )
+ ->method( 'insert' );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->once() )
+ ->method( 'newByType' )
+ ->will( $this->returnValue( $entityIdDisposerJob ) );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DisposeJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->isApiTask = false;
+ $instance->setEnabledFeatures( SMW_ADM_DISPOSAL );
+ $instance->handleRequest( $webRequest );
+ }
+
+ public function testHandleRequestOnPendingJob() {
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'hasPendingJob' )
+ ->with( $this->equalTo( 'smw.entityIdDisposer' ) )
+ ->will( $this->returnValue( true ) );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->never() )
+ ->method( 'newByType' );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DisposeJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->setEnabledFeatures( SMW_ADM_DISPOSAL );
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DuplicateLookupTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DuplicateLookupTaskHandlerTest.php
new file mode 100644
index 00000000..0f8c1fb7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/DuplicateLookupTaskHandlerTest.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\DuplicateLookupTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\DuplicateLookupTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DuplicateLookupTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ DuplicateLookupTaskHandler::class,
+ new DuplicateLookupTaskHandler( $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new DuplicateLookupTaskHandler(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $this->outputFormatter->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' );
+
+ $instance = new DuplicateLookupTaskHandler(
+ $this->outputFormatter
+ );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/EntityLookupTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/EntityLookupTaskHandlerTest.php
new file mode 100644
index 00000000..65927031
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/EntityLookupTaskHandlerTest.php
@@ -0,0 +1,222 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\EntityLookupTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\EntityLookupTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class EntityLookupTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+ private $connection;
+ private $htmlFormRenderer;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\EntityLookupTaskHandler',
+ new EntityLookupTaskHandler( $this->store, $this->htmlFormRenderer, $this->outputFormatter )
+ );
+ }
+
+ public function testGetHml() {
+
+ $this->outputFormatter->expects( $this->any() )
+ ->method( 'getSpecialPageLinkWith' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'action' => 'lookup' ] ) );
+
+ $instance = new EntityLookupTaskHandler(
+ $this->store,
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testPerformAction() {
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addInputField',
+ 'addSubmitButton',
+ 'addNonBreakingSpace',
+ 'addCheckbox'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new EntityLookupTaskHandler(
+ $this->store,
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->atLeastOnce() )
+ ->method( 'matchEditToken' )
+ ->will( $this->returnValue( true ) );
+
+ $instance->setUser(
+ $user
+ );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance->handleRequest( $webRequest );
+ }
+
+ public function testPerformActionWithId() {
+
+ $this->connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $manualEntryLogger = $this->getMockBuilder( '\SMW\MediaWiki\ManualEntryLogger' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $manualEntryLogger->expects( $this->once() )
+ ->method( 'log' );
+
+ $this->testEnvironment->registerObject( 'ManualEntryLogger', $manualEntryLogger );
+
+ $entityIdDisposerJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\EntityIdDisposerJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->atLeastOnce() )
+ ->method( 'newEntityIdDisposerJob' )
+ ->will( $this->returnValue( $entityIdDisposerJob ) );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addInputField',
+ 'addSubmitButton',
+ 'addNonBreakingSpace',
+ 'addCheckbox'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->atLeastOnce() )
+ ->method( 'matchEditToken' )
+ ->will( $this->returnValue( true ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $webRequest->expects( $this->at( 1 ) )
+ ->method( 'getText' )
+ ->with( $this->equalTo( 'id' ) )
+ ->will( $this->returnValue( 42 ) );
+
+ $webRequest->expects( $this->at( 2 ) )
+ ->method( 'getText' )
+ ->with( $this->equalTo( 'dispose' ) )
+ ->will( $this->returnValue( 'yes' ) );
+
+ $webRequest->expects( $this->at( 3 ) )
+ ->method( 'getText' )
+ ->with( $this->equalTo( 'action' ) )
+ ->will( $this->returnValue( 'lookup' ) );
+
+ $instance = new EntityLookupTaskHandler(
+ $this->store,
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->setEnabledFeatures( SMW_ADM_DISPOSAL );
+ $instance->setUser( $user );
+
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/FulltextSearchTableRebuildJobTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/FulltextSearchTableRebuildJobTaskHandlerTest.php
new file mode 100644
index 00000000..290c9368
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/FulltextSearchTableRebuildJobTaskHandlerTest.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\FulltextSearchTableRebuildJobTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\FulltextSearchTableRebuildJobTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FulltextSearchTableRebuildJobTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $htmlFormRenderer;
+ private $outputFormatter;
+ private $jobQueue;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $this->jobQueue );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\FulltextSearchTableRebuildJobTaskHandler',
+ new FulltextSearchTableRebuildJobTaskHandler( $this->htmlFormRenderer, $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addSubmitButton'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new FulltextSearchTableRebuildJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->getHtml();
+ }
+
+ public function testHandleRequestOnNonPendingJob() {
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'hasPendingJob' )
+ ->with( $this->equalTo( 'smw.fulltextSearchTableRebuild' ) )
+ ->will( $this->returnValue( false ) );
+
+ $fulltextSearchTableRebuildJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\FulltextSearchTableRebuildJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $fulltextSearchTableRebuildJob->expects( $this->once() )
+ ->method( 'insert' );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->once() )
+ ->method( 'newByType' )
+ ->will( $this->returnValue( $fulltextSearchTableRebuildJob ) );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new FulltextSearchTableRebuildJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->isApiTask = false;
+ $instance->setEnabledFeatures( SMW_ADM_FULLT );
+ $instance->handleRequest( $webRequest );
+ }
+
+ public function testHandleRequestOnPendingJob() {
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'hasPendingJob' )
+ ->with( $this->equalTo( 'smw.fulltextSearchTableRebuild' ) )
+ ->will( $this->returnValue( true ) );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->never() )
+ ->method( 'newByType' );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new FulltextSearchTableRebuildJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->setEnabledFeatures( SMW_ADM_FULLT );
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OperationalStatisticsListTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OperationalStatisticsListTaskHandlerTest.php
new file mode 100644
index 00000000..8e7f144d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OperationalStatisticsListTaskHandlerTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\OperationalStatisticsListTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\OperationalStatisticsListTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class OperationalStatisticsListTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ OperationalStatisticsListTaskHandler::class,
+ new OperationalStatisticsListTaskHandler( $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new OperationalStatisticsListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testIsTaskFor() {
+
+ $instance = new OperationalStatisticsListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $this->assertTrue(
+ $instance->isTaskFor( 'stats')
+ );
+ }
+
+ public function testHandleRequest() {
+
+ $semanticStatistics = [
+ 'PROPUSES' => 0,
+ 'ERRORUSES' => 0,
+ 'USEDPROPS' => 0,
+ 'TOTALPROPS' => 0,
+ 'OWNPAGE' => 0,
+ 'DECLPROPS' => 0,
+ 'DELETECOUNT' => 0,
+ 'SUBOBJECTS' => 0,
+ 'QUERY' => 0,
+ 'CONCEPTS' => 0
+ ];
+
+ $this->store->expects( $this->once() )
+ ->method( 'getStatistics' )
+ ->will( $this->returnValue( $semanticStatistics ) );
+
+ $this->outputFormatter->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' );
+
+ $instance = new OperationalStatisticsListTaskHandler(
+ $this->outputFormatter
+ );
+
+ $instance->setStore( $this->store );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance->handleRequest( $webRequest );
+ }
+
+ public function testHandleSubRequest() {
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $taskHandler = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\TaskHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $taskHandler->expects( $this->once() )
+ ->method( 'isTaskFor' )
+ ->will( $this->returnValue( true ) );
+
+ $taskHandler->expects( $this->once() )
+ ->method( 'handleRequest' )
+ ->with( $this->equalTo( $webRequest ) );
+
+ $instance = new OperationalStatisticsListTaskHandler(
+ $this->outputFormatter,
+ [ $taskHandler ]
+ );
+
+ $instance->setStore( $this->store );
+
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OutputFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OutputFormatterTest.php
new file mode 100644
index 00000000..3f0d7782
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/OutputFormatterTest.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\OutputFormatter;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\OutputFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class OutputFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $outputPage;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\OutputFormatter',
+ new OutputFormatter( $this->outputPage )
+ );
+ }
+
+ public function testGetSpecialPageLinkWith() {
+
+ $instance = new OutputFormatter( $this->outputPage );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getSpecialPageLinkWith()
+ );
+ }
+
+ public function testEncodeAsJson() {
+
+ $instance = new OutputFormatter( $this->outputPage );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->encodeAsJson( [] )
+ );
+ }
+
+ public function testAddParentLink() {
+
+ $this->outputPage->expects( $this->once() )
+ ->method( 'prependHTML' );
+
+ $instance = new OutputFormatter( $this->outputPage );
+ $instance->addParentLink();
+ }
+
+ public function testSetPageTitle() {
+
+ $this->outputPage->expects( $this->once() )
+ ->method( 'setPageTitle' );
+
+ $instance = new OutputFormatter( $this->outputPage );
+ $instance->setPageTitle( 'Foo' );
+ }
+
+ public function testAddHTML() {
+
+ $this->outputPage->expects( $this->once() )
+ ->method( 'addHTML' );
+
+ $instance = new OutputFormatter( $this->outputPage );
+ $instance->addHTML( 'Foo' );
+ }
+
+ public function testAddWikiText() {
+
+ $this->outputPage->expects( $this->once() )
+ ->method( 'addWikiText' );
+
+ $instance = new OutputFormatter( $this->outputPage );
+ $instance->addWikiText( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/PropertyStatsRebuildJobTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/PropertyStatsRebuildJobTaskHandlerTest.php
new file mode 100644
index 00000000..cbccd77c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/PropertyStatsRebuildJobTaskHandlerTest.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\PropertyStatsRebuildJobTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\PropertyStatsRebuildJobTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyStatsRebuildJobTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $htmlFormRenderer;
+ private $outputFormatter;
+ private $jobQueue;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $this->jobQueue );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\PropertyStatsRebuildJobTaskHandler',
+ new PropertyStatsRebuildJobTaskHandler( $this->htmlFormRenderer, $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addSubmitButton'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new PropertyStatsRebuildJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->getHtml();
+ }
+
+ public function testHandleRequestOnNonPendingJob() {
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'hasPendingJob' )
+ ->with( $this->equalTo( 'smw.propertyStatisticsRebuild' ) )
+ ->will( $this->returnValue( false ) );
+
+ $propertyStatisticsRebuildJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\PropertyStatisticsRebuildJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyStatisticsRebuildJob->expects( $this->once() )
+ ->method( 'insert' );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->once() )
+ ->method( 'newByType' )
+ ->will( $this->returnValue( $propertyStatisticsRebuildJob ) );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyStatsRebuildJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->isApiTask = false;
+ $instance->setEnabledFeatures( SMW_ADM_PSTATS );
+ $instance->handleRequest( $webRequest );
+ }
+
+ public function testHandleRequestOnPendingJob() {
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'hasPendingJob' )
+ ->with( $this->equalTo( 'smw.propertyStatisticsRebuild' ) )
+ ->will( $this->returnValue( true ) );
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->never() )
+ ->method( 'newByType' );
+
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyStatsRebuildJobTaskHandler(
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->setEnabledFeatures( SMW_ADM_PSTATS );
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/SupportListTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/SupportListTaskHandlerTest.php
new file mode 100644
index 00000000..4808a67b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/SupportListTaskHandlerTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\SupportListTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\SupportListTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SupportListTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $htmlFormRenderer;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\SupportListTaskHandler',
+ new SupportListTaskHandler( $this->htmlFormRenderer )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addSubmitButton',
+ 'setActionUrl'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new SupportListTaskHandler(
+ $this->htmlFormRenderer
+ );
+
+ $instance->getHtml();
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TableSchemaTaskHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TableSchemaTaskHandlerTest.php
new file mode 100644
index 00000000..d6d0d371
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TableSchemaTaskHandlerTest.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\TableSchemaTaskHandler;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\TableSchemaTaskHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TableSchemaTaskHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+ private $htmlFormRenderer;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\Admin\TableSchemaTaskHandler',
+ new TableSchemaTaskHandler( $this->store, $this->htmlFormRenderer, $this->outputFormatter )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addSubmitButton'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new TableSchemaTaskHandler(
+ $this->store,
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->getHtml();
+ }
+
+ public function testHandleRequest() {
+
+ $this->store->expects( $this->once() )
+ ->method( 'setup' );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $webRequest->expects( $this->once() )
+ ->method( 'getVal' )
+ ->will( $this->returnValue( 'done' ) );
+
+ $instance = new TableSchemaTaskHandler(
+ $this->store,
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $instance->setEnabledFeatures( SMW_ADM_SETUP );
+ $instance->handleRequest( $webRequest );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TaskHandlerFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TaskHandlerFactoryTest.php
new file mode 100644
index 00000000..446b7f9f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Admin/TaskHandlerFactoryTest.php
@@ -0,0 +1,148 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Admin;
+
+use SMW\MediaWiki\Specials\Admin\TaskHandlerFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Admin\TaskHandlerFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TaskHandlerFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $htmlFormRenderer;
+ private $outputFormatter;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->outputFormatter = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Admin\OutputFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TaskHandlerFactory::class,
+ new TaskHandlerFactory( $this->store, $this->htmlFormRenderer, $this->outputFormatter )
+ );
+ }
+
+ public function testGetTaskHandlerList() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $adminFeatures = '';
+
+ $instance = new TaskHandlerFactory(
+ $this->store,
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTaskHandlerList( $user, $adminFeatures )
+ );
+ }
+
+ /**
+ * @dataProvider methodProvider
+ */
+ public function testCanConstructByFactory( $method, $expected ) {
+
+ $instance = new TaskHandlerFactory(
+ $this->store,
+ $this->htmlFormRenderer,
+ $this->outputFormatter
+ );
+
+ $this->assertInstanceOf(
+ $expected,
+ call_user_func( [ $instance, $method ] )
+ );
+ }
+
+ public function methodProvider() {
+
+ $provider[] = [
+ 'newTableSchemaTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\TableSchemaTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newSupportListTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\SupportListTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newConfigurationListTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\ConfigurationListTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newOperationalStatisticsListTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\OperationalStatisticsListTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newEntityLookupTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\EntityLookupTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newDataRefreshJobTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\DataRefreshJobTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newDisposeJobTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\DisposeJobTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newPropertyStatsRebuildJobTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\PropertyStatsRebuildJobTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newFulltextSearchTableRebuildJobTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\FulltextSearchTableRebuildJobTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newDeprecationNoticeTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\DeprecationNoticeTaskHandler'
+ ];
+
+ $provider[] = [
+ 'newDuplicateLookupTaskHandler',
+ '\SMW\MediaWiki\Specials\Admin\DuplicateLookupTaskHandler'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/DownloadLinksWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/DownloadLinksWidgetTest.php
new file mode 100644
index 00000000..52a8e7a0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/DownloadLinksWidgetTest.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\DownloadLinksWidget;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\DownloadLinksWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DownloadLinksWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testOnNull() {
+
+ $this->assertEmpty(
+ DownloadLinksWidget::downloadLinks( null )
+ );
+ }
+
+ public function testLinks() {
+
+ $infolink = $this->getMockBuilder( '\SMWInfolink' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $infolink->expects( $this->atLeastOnce() )
+ ->method( 'setParameter' );
+
+ $this->assertContains(
+ '<div id="ask-export-links" class="smw-ask-downloadlinks export-links">',
+ DownloadLinksWidget::downloadLinks( $infolink )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ErrorWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ErrorWidgetTest.php
new file mode 100644
index 00000000..7a67c520
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ErrorWidgetTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\ErrorWidget;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\ErrorWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ErrorWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testSessionFailure() {
+
+ $this->assertInternalType(
+ 'string',
+ ErrorWidget::sessionFailure()
+ );
+ }
+
+ public function testNoScript() {
+
+ $this->assertInternalType(
+ 'string',
+ ErrorWidget::noScript()
+ );
+ }
+
+ public function testNoResult() {
+
+ $this->assertInternalType(
+ 'string',
+ ErrorWidget::noResult()
+ );
+ }
+
+ /**
+ * @dataProvider queryErrorProvider
+ */
+ public function testGetFormattedQueryErrorElement( $errors, $expected ) {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( $errors ) );
+
+ $this->assertEquals(
+ $expected,
+ ErrorWidget::queryError( $query )
+ );
+ }
+
+ public function queryErrorProvider() {
+
+ $provider[] = [
+ '',
+ ''
+ ];
+
+ $provider[] = [
+ [ 'Foo' ],
+ '<div id="result-error" class="smw-callout smw-callout-error">Foo</div>'
+ ];
+
+ $provider[] = [
+ [ 'Foo', 'Bar' ],
+ '<div id="result-error" class="smw-callout smw-callout-error"><ul><li>Foo</li><li>Bar</li></ul></div>'
+ ];
+
+ $provider[] = [
+ [ 'Foo', [ 'Bar' ] ],
+ '<div id="result-error" class="smw-callout smw-callout-error"><ul><li>Foo</li><li>Bar</li></ul></div>'
+ ];
+
+ // Filter duplicate
+ $provider[] = [
+ [ 'Foo', [ 'Bar' ], 'Bar' ],
+ '<div id="result-error" class="smw-callout smw-callout-error"><ul><li>Foo</li><li>Bar</li></ul></div>'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/FormatListWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/FormatListWidgetTest.php
new file mode 100644
index 00000000..efceebd6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/FormatListWidgetTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\FormatListWidget;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\FormatListWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FormatListWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testEmptyParameters() {
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stringValidator->assertThatStringContains(
+ [
+ '<span class="smw-ask-format-list"><input type="hidden" value="yes" name="eq"',
+ '<option value="broadtable" selected="">.*</option>'
+ ],
+ FormatListWidget::selectList( $title, [] )
+ );
+ }
+
+ public function testSetResultFormats() {
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ FormatListWidget::setResultFormats(
+ [
+ 'rdf' => 'SomeClassReference'
+ ]
+ );
+
+ $stringValidator->assertThatStringContains(
+ [
+ '<option value="broadtable">.*</option>',
+ '<option data-isexport="1" value="rdf" selected="">.*</option>'
+ ],
+ FormatListWidget::selectList( $title, [ 'format' => 'rdf' ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HelpWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HelpWidgetTest.php
new file mode 100644
index 00000000..f1f9e204
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HelpWidgetTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\HelpWidget;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\HelpWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HelpWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testSessionFailure() {
+
+ $this->assertContains(
+ 'ask-help',
+ HelpWidget::html()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HtmlFormTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HtmlFormTest.php
new file mode 100644
index 00000000..eaa85204
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/HtmlFormTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\HtmlForm;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\HtmlForm
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlFormTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ HtmlForm::class,
+ new HtmlForm( $title )
+ );
+ }
+
+ public function testGetForm_IsEditMode() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getExtraPrintouts' )
+ ->will( $this->returnValue( [] ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getSortKeys' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->atLeastOnce() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $instance = new HtmlForm( $title );
+ $instance->isEditMode( true );
+
+ $text = '';
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getForm( $urlArgs, $queryResult, $text )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/LinksWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/LinksWidgetTest.php
new file mode 100644
index 00000000..152d494a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/LinksWidgetTest.php
@@ -0,0 +1,133 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\LinksWidget;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\LinksWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class LinksWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testFieldset() {
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::fieldset()
+ );
+ }
+
+ public function testEmbeddedCodeLink() {
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::embeddedCodeLink()
+ );
+ }
+
+ public function testEmbeddedCodeBlock() {
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::embeddedCodeBlock( 'Foo' )
+ );
+ }
+
+ public function testResultSubmitLinkHide() {
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::resultSubmitLink( true )
+ );
+ }
+
+ public function testResultSubmitLinkShow() {
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::resultSubmitLink( false )
+ );
+ }
+
+ public function testShowHideLink() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::showHideLink( $title, $urlArgs )
+ );
+ }
+
+ public function testDebugLink() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::debugLink( $title, $urlArgs )
+ );
+ }
+
+ public function testNoQCacheLink() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::noQCacheLink( $title, $urlArgs, true )
+ );
+ }
+
+ public function testNoQCacheLinkOnFalseFromCache() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertEmpty(
+ LinksWidget::noQCacheLink( $title, $urlArgs, false )
+ );
+ }
+
+ public function testClipboardLink() {
+
+ $infolink = $this->getMockBuilder( '\SMWInfolink' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'string',
+ LinksWidget::clipboardLink( $infolink )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/NavigationLinksWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/NavigationLinksWidgetTest.php
new file mode 100644
index 00000000..6e0dc5da
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/NavigationLinksWidgetTest.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\NavigationLinksWidget;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\NavigationLinksWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class NavigationLinksWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testNavigation() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs->expects( $this->any() )
+ ->method( 'toArray' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->assertInternalType(
+ 'string',
+ NavigationLinksWidget::navigationLinks( $title, $urlArgs, 20, false )
+ );
+ }
+
+ public function testSetMaxInlineLimit() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs->expects( $this->any() )
+ ->method( 'toArray' )
+ ->will( $this->returnValue( [] ) );
+
+ NavigationLinksWidget::setMaxInlineLimit( 300 );
+
+ $result = NavigationLinksWidget::navigationLinks( $title, $urlArgs, 20, false );
+
+ $this->assertContains(
+ 'class="page-link">250</a>',
+ $result
+ );
+ }
+
+ public function testNavigationLinksOnZeroCountResult() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ NavigationLinksWidget::setMaxInlineLimit( 300 );
+
+ $result = NavigationLinksWidget::navigationLinks( $title, $urlArgs, 0, false );
+
+ $this->assertEmpty(
+ $result
+ );
+ }
+
+ public function testOffsetLimit() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $urlArgs = $this->getMockBuilder( '\SMW\MediaWiki\Specials\Ask\UrlArgs' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'get', 'set' ] )
+ ->getMock();
+
+ $urlArgs->expects( $this->at( 0 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'limit' ) )
+ ->will( $this->returnValue( 3 ) );
+
+ $urlArgs->expects( $this->at( 1 ) )
+ ->method( 'get' )
+ ->with( $this->equalTo( 'offset' ) )
+ ->will( $this->returnValue( 10 ) );
+
+ NavigationLinksWidget::setMaxInlineLimit( 300 );
+ NavigationLinksWidget::navigationLinks( $title, $urlArgs, 20, true );
+ }
+
+ public function testTopLinks() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertContains(
+ '<div id="ask-toplinks" class="smw-ask-toplinks"><span class="float-left"><a href="#options">',
+ NavigationLinksWidget::topLinks( $title, [ 'options' ] )
+ );
+
+ $this->assertContains(
+ '<div id="ask-toplinks" class="smw-ask-toplinks"><span class="float-left"></span>&#160;<span class="float-right">',
+ NavigationLinksWidget::topLinks( $title, [ 'empty' ] )
+ );
+ }
+
+ public function testHiddenTopLinks() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertEmpty(
+ NavigationLinksWidget::topLinks( $title, [] )
+ );
+ }
+
+ public function testBasicLinks() {
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $stringValidator->assertThatStringContains(
+ [
+ '<div class="smw-ask-actions-nav">foo</div>',
+ ],
+ NavigationLinksWidget::basicLinks( 'foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParameterInputTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParameterInputTest.php
new file mode 100644
index 00000000..93154657
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParameterInputTest.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\ParameterInput;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\ParameterInput
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ParameterInputTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $paramDefinition = $this->getMockBuilder( '\ParamProcessor\ParamDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ParameterInput::class,
+ new ParameterInput( $paramDefinition, '' )
+ );
+ }
+
+ /**
+ * @dataProvider listValueProvider
+ */
+ public function testGetHtmlOnCheckboxList( $currentValue, $allowedValues, $expected ) {
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $paramDefinition = $this->getMockBuilder( '\ParamProcessor\ParamDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $paramDefinition->expects( $this->atLeastOnce() )
+ ->method( 'getAllowedValues' )
+ ->will( $this->returnValue( $allowedValues ) );
+
+ $paramDefinition->expects( $this->any() )
+ ->method( 'isList' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new ParameterInput(
+ $paramDefinition,
+ $currentValue
+ );
+
+ $stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function listValueProvider() {
+
+ $provider[] = [
+ 'Foo',
+ [ 'Foo', 'Bar' ],
+ [
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="Foo" checked="".*><tt>Foo</tt></span>',
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="Bar".*><tt>Bar</tt></span>'
+ ],
+
+ ];
+
+ $provider[] = [
+ [ 'Foo' ],
+ [ 'Foo', 'Bar' ],
+ [
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="Foo" checked="".*><tt>Foo</tt></span>',
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="Bar".*><tt>Bar</tt></span>'
+ ],
+
+ ];
+
+ $provider[] = [
+ [ 'Foo, Bar' ],
+ [ 'Foo', 'Bar' ],
+ [
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="Foo" checked="".*><tt>Foo</tt></span>',
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="Bar" checked="".*><tt>Bar</tt></span>'
+ ],
+
+ ];
+
+ $provider[] = [
+ [ 'Foo,foo bar' ],
+ [ 'Foo', 'foo bar' ],
+ [
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="Foo" checked="".*><tt>Foo</tt></span>',
+ '<span class="parameter-checkbox-input" style="white-space: nowrap; padding-right: 5px;"><input type="checkbox" name="[]" value="foo bar" checked="".*><tt>foo bar</tt></span>'
+ ],
+
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersProcessorTest.php
new file mode 100644
index 00000000..532b9d48
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersProcessorTest.php
@@ -0,0 +1,242 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\ParametersProcessor;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\ParametersProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ParametersProcessorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testEmpty() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'array',
+ ParametersProcessor::process( $request, [] )
+ );
+ }
+
+ public function testParameters() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parameters = [
+ '[[Foo::bar]]',
+ '|?Foo=foobar'
+ ];
+
+ $result = ParametersProcessor::process( $request, $parameters );
+
+ $this->assertEquals(
+ '[[Foo::bar]]',
+ $result[0]
+ );
+ }
+
+ public function testParameters_Printrequest_PlusPipe() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parameters = [
+ '[[Foo::bar]]',
+ '|?Foo=Bar|+index=1'
+ ];
+
+ $result = ParametersProcessor::process( $request, $parameters );
+
+ $this->assertEquals(
+ 'Bar|+index=1',
+ $result[1]['|?foo']
+ );
+ }
+
+ public function testParameters_Printrequest_WikiLink() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parameters = [
+ '[[Foo::bar]]',
+ '|?Foo=[[Some|other]]'
+ ];
+
+ $result = ParametersProcessor::process( $request, $parameters );
+
+ $this->assertEquals(
+ '[[Some|other]]',
+ $result[1]['|?foo']
+ );
+ }
+
+ public function testParameters_Printrequest_WikiLink_PlusPipe() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parameters = [
+ '[[Foo::bar]]',
+ '|?Foo=[[Some|other]]|+index=1'
+ ];
+
+ $result = ParametersProcessor::process( $request, $parameters );
+
+ $this->assertEquals(
+ '[[Some|other]]|+index=1',
+ $result[1]['|?foo']
+ );
+ }
+
+ public function testParametersWithDefaults() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $request->expects( $this->at( 5 ) )
+ ->method( 'getVal' )
+ ->with(
+ $this->equalTo( 'offset' ),
+ $this->equalTo( 0 ) );
+
+ $request->expects( $this->at( 6 ) )
+ ->method( 'getVal' )
+ ->with(
+ $this->equalTo( 'limit' ),
+ $this->equalTo( 42 ) );
+
+ ParametersProcessor::setDefaultLimit( 42 );
+
+ $parameters = [
+ '[[Foo::bar]]',
+ '|?Foo=foobar'
+ ];
+
+ ParametersProcessor::process( $request, $parameters );
+ }
+
+ public function testParameters_Sort_FirstEmpty() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $request->expects( $this->at( 3 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'sort_num' ) )
+ ->will( $this->returnValue( [ '', '', 'Foo' ] ) );
+
+ $request->expects( $this->at( 4 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'order_num' ) )
+ ->will( $this->returnValue( [ 'asc', 'desc' ] ) );
+
+ $parameters = [
+ '[[Foo::bar]]'
+ ];
+
+ list( $q, $p, $po ) = ParametersProcessor::process(
+ $request,
+ $parameters
+ );
+
+ $this->assertSame(
+ $p['sort'],
+ ',Foo'
+ );
+
+ $this->assertSame(
+ $p['order'],
+ 'asc,desc'
+ );
+ }
+
+ public function testParameters_Sort_FirstNotEmpty() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $request->expects( $this->at( 3 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'sort_num' ) )
+ ->will( $this->returnValue( [ 'Foo', '' ] ) );
+
+ $request->expects( $this->at( 4 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'order_num' ) )
+ ->will( $this->returnValue( [ 'asc', 'desc' ] ) );
+
+ $parameters = [
+ '[[Foo::bar]]'
+ ];
+
+ list( $q, $p, $po ) = ParametersProcessor::process(
+ $request,
+ $parameters
+ );
+
+ $this->assertSame(
+ $p['sort'],
+ 'Foo'
+ );
+
+ $this->assertSame(
+ $p['order'],
+ 'asc'
+ );
+ }
+
+ public function testParametersOn_p_Array_Request() {
+
+ $request = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $request->expects( $this->at( 0 ) )
+ ->method( 'getCheck' )
+ ->with( $this->equalTo( 'q' ) )
+ ->will( $this->returnValue( true ) );
+
+ $request->expects( $this->at( 1 ) )
+ ->method( 'getVal' )
+ ->with( $this->equalTo( 'p' ) )
+ ->will( $this->returnValue( '' ) );
+
+ $request->expects( $this->at( 2 ) )
+ ->method( 'getArray' )
+ ->with( $this->equalTo( 'p' ) )
+ ->will( $this->returnValue( [ 'foo' => [ 'Bar', 'foobar' ] ] ) );
+
+ $parameters = [];
+
+ $res = ParametersProcessor::process( $request, $parameters );
+
+ $this->assertEquals(
+ [
+ 'foo' => 'Bar,foobar',
+ 'format' => 'broadtable',
+ 'offset' => null,
+ 'limit' => null
+ ],
+ $res[1]
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersWidgetTest.php
new file mode 100644
index 00000000..ffb6fb48
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/ParametersWidgetTest.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\ParametersWidget;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\ParametersWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ParametersWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+
+ protected function setUp() {
+ $testEnvironment = new TestEnvironment();
+
+ $this->stringValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testFieldset() {
+
+ $parameters = [];
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ '<fieldset><legend>.*</legend><span class="smw-ask-format-list">',
+ '<input type="checkbox" id="options-toggle"/><div id="options-list" class="options-list"><div class="options-parameter-list">'
+ ],
+ ParametersWidget::fieldset( \Title::newFromText( 'Foo' ), $parameters )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testCreateParametersForm( $format, $parameters, $expected ) {
+
+ $parameters['format'] = $format;
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ ParametersWidget::parameterList( $parameters )
+ );
+ }
+
+ public function parametersProvider() {
+
+ $provider[] = [
+ '',
+ [],
+ '<div class="smw-table smw-ask-options-list" width="100%"><div class="smw-table-row smw-ask-options-row-odd"></div></div>'
+ ];
+
+ $provider[] = [
+ 'table',
+ [],
+ [
+ '<div class="smw-table smw-ask-options-list" width="100%"',
+ '<input class="parameter-number-input" size="6" style="width: 95%;" value="50" name="p[limit]"',
+ '<input class="parameter-number-input" size="6" style="width: 95%;" value="0" name="p[offset]"'
+ ]
+ ];
+
+ $provider[] = [
+ 'table',
+ [
+ 'limit' => 9999,
+ 'offset' => 42
+ ],
+ [
+ '<input class="parameter-number-input" size="6" style="width: 95%;" value="9999" name="p[limit]"',
+ '<input class="parameter-number-input" size="6" style="width: 95%;" value="42" name="p[offset]"'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/QueryInputWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/QueryInputWidgetTest.php
new file mode 100644
index 00000000..b7b0023e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/QueryInputWidgetTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\QueryInputWidget;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\QueryInputWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class QueryInputWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testInput() {
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $stringValidator->assertThatStringContains(
+ [
+ '<div class="smw-table" style="width: 100%;"><div class="smw-table-row">',
+ '<div class="smw-table-cell smw-ask-condition slowfade"><fieldset><legend>.*</legend><textarea id="ask-query-condition" class="smw-ask-query-condition" name="q" rows="6" placeholder="...">Foo</textarea>',
+ '<div class="smw-table-cell smw-ask-printhead slowfade"><fieldset><legend>.*</legend><textarea id="smw-property-input" class="smw-ask-query-printout" name="po" rows="6" placeholder="...">Bar</textarea>'
+ ],
+ QueryInputWidget::table( 'Foo', 'Bar' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/SortWidgetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/SortWidgetTest.php
new file mode 100644
index 00000000..04ab109c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/SortWidgetTest.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\SortWidget;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\SortWidget
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SortWidgetTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+
+ protected function setUp() {
+ $testEnvironment = new TestEnvironment();
+
+ $this->stringValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testDisabled() {
+
+ SortWidget::setSortingSupport( false );
+
+ $this->assertEmpty(
+ SortWidget::sortSection( [] )
+ );
+ }
+
+ public function testEnabledWithEmptyParameters() {
+
+ SortWidget::setSortingSupport( true );
+
+ $this->assertContains(
+ '<div id="options-sort" class="smw-ask-options-sort">',
+ SortWidget::sortSection( [] )
+ );
+ }
+
+ public function testEnabledWithParameters() {
+
+ SortWidget::setSortingSupport( true );
+ SortWidget::setRandSortingSupport( true );
+
+ $result = SortWidget::sortSection(
+ [
+ 'sort' => 'Foo,bar',
+ 'order' => 'asc,DESC'
+ ]
+ );
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ '<div id="sort_div_0" class="smw-ask-sort-input">',
+ '<input name="sort_num[]" size="35" class="smw-property-input autocomplete-arrow" value="Foo"',
+ '<select name="order_num[]"><option selected="selected" value="asc">'
+ ],
+ $result
+ );
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ '<div id="sort_div_1" class="smw-ask-sort-input">',
+ '<input name="sort_num[]" size="35" class="smw-property-input autocomplete-arrow" value="bar"',
+ '<select name="order_num[]"><option value="asc">.*</option><option selected="selected" value="desc">'
+ ],
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/UrlArgsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/UrlArgsTest.php
new file mode 100644
index 00000000..3eeafa8f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Ask/UrlArgsTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Ask;
+
+use SMW\MediaWiki\Specials\Ask\UrlArgs;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Ask\UrlArgs
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class UrlArgsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testToString() {
+
+ $instance = new UrlArgs();
+
+ $instance->set( 'foo', 42 );
+ $instance->set( 'bar', 1001 );
+ $instance->setFragment( 'foobar' );
+
+ $this->assertContains(
+ 'foo=42&bar=1001#foobar',
+ $instance->__toString()
+ );
+ }
+
+ public function testGet() {
+
+ $instance = new UrlArgs();
+
+ $instance->set( 'foo', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->get( 'foo' )
+ );
+
+ $this->assertEquals(
+ null,
+ $instance->get( 42 )
+ );
+ }
+
+ public function testDelete() {
+
+ $instance = new UrlArgs();
+
+ $instance->set( 'foo', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->get( 'foo' )
+ );
+
+ $instance->delete( 'foo' );
+
+ $this->assertEquals(
+ null,
+ $instance->get( 'foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/FieldBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/FieldBuilderTest.php
new file mode 100644
index 00000000..351f113e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/FieldBuilderTest.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Browse;
+
+use SMW\MediaWiki\Specials\Browse\FieldBuilder;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Browse\FieldBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FieldBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCreateQueryForm() {
+
+ $this->assertInternalType(
+ 'string',
+ FieldBuilder::createQueryForm( 'Foo' )
+ );
+ }
+
+ public function testCreateLink() {
+
+ $parameters = [];
+
+ $this->assertInternalType(
+ 'string',
+ FieldBuilder::createLink( 'Foo', $parameters )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/GroupFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/GroupFormatterTest.php
new file mode 100644
index 00000000..a6412c4a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/GroupFormatterTest.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Browse;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Specials\Browse\GroupFormatter;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Browse\GroupFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class GroupFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ private $propertySpecificationLookup;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ GroupFormatter::class,
+ new GroupFormatter( $this->propertySpecificationLookup )
+ );
+ }
+
+ public function testFindGroupMembership() {
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getPropertyGroup' )
+ ->will( $this->returnValue( new DIWikiPage( 'Bar', NS_CATEGORY ) ) );
+
+ $instance = new GroupFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $properties = [
+ new DIProperty( 'Foo' )
+ ];
+
+ $instance->findGroupMembership( $properties );
+
+ $this->assertTrue(
+ $instance->hasGroups()
+ );
+
+ $this->assertTrue(
+ $instance->isLastGroup( 'Bar' )
+ );
+
+ $this->assertArrayHasKey(
+ 'Bar',
+ $properties
+ );
+
+ $this->assertContains(
+ '<span class="group-link">',
+ $instance->getGroupLink( 'Bar' )
+ );
+ }
+
+ public function testFindGroupMembershipWhereShowGroupIsDisabled() {
+
+ $this->propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getPropertyGroup' )
+ ->will( $this->returnValue( new DIWikiPage( 'Bar', NS_CATEGORY ) ) );
+
+ $instance = new GroupFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $instance->showGroup( false );
+
+ $properties = [
+ new DIProperty( 'Foo' )
+ ];
+
+ $instance->findGroupMembership( $properties );
+
+ $this->assertFalse(
+ $instance->hasGroups()
+ );
+
+ $this->assertFalse(
+ $instance->isLastGroup( 'Bar' )
+ );
+ }
+
+ public function testGetMessageClassLink() {
+
+ $instance = new GroupFormatter(
+ $this->propertySpecificationLookup
+ );
+
+ $di = new DIWikiPage( 'Foo bar', NS_CATEGORY );
+
+ $this->assertContains(
+ 'smw-property-group-label-foo-bar',
+ $instance->getMessageClassLink( GroupFormatter::MESSAGE_GROUP_LABEL, $di )
+ );
+
+ $this->assertContains(
+ 'smw-property-group-description-foo-bar',
+ $instance->getMessageClassLink( GroupFormatter::MESSAGE_GROUP_DESCRIPTION, $di )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/HtmlBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/HtmlBuilderTest.php
new file mode 100644
index 00000000..68707252
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/HtmlBuilderTest.php
@@ -0,0 +1,195 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Browse;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Specials\Browse\HtmlBuilder;
+use SMW\SemanticData;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Browse\HtmlBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class HtmlBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ // Disable a possible active hook execution
+ $this->testEnvironment = new TestEnvironment( [
+ 'smwgEnabledQueryDependencyLinksStore' => false
+ ] );
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new HtmlBuilder(
+ $this->store,
+ DIWikiPage::newFromText( 'Foo' )
+ );
+
+ $this->assertInstanceOf(
+ HtmlBuilder::class,
+ $instance
+ );
+ }
+
+ public function testBuildEmptyHTML() {
+
+ $instance = new HtmlBuilder(
+ $this->store,
+ DIWikiPage::newFromText( 'Foo' )
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->buildEmptyHTML()
+ );
+ }
+
+ public function testBuildHTML() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( new SemanticData( $subject ) ) );
+
+ $instance = new HtmlBuilder(
+ $this->store,
+ $subject
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->buildHTML()
+ );
+ }
+
+ public function testLegacy() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( new SemanticData( $subject ) ) );
+
+ $instance = new HtmlBuilder(
+ $this->store,
+ $subject
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->legacy()
+ );
+ }
+
+ public function testPlaceholder() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( new SemanticData( $subject ) ) );
+
+ $instance = new HtmlBuilder(
+ $this->store,
+ $subject
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->placeholder()
+ );
+ }
+
+ public function testBuildHTMLWithOptions() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( new SemanticData( $subject ) ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getInProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new HtmlBuilder(
+ $this->store,
+ $subject
+ );
+
+ $options = [
+ 'offset' => 0,
+ 'showAll' => true,
+ 'showInverse' => false,
+ 'dir' => 'both',
+ 'printable' => ''
+ ];
+
+ $instance->setOptions(
+ $options
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->buildHTML()
+ );
+ }
+
+ public function testOptions() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $instance = new HtmlBuilder(
+ $this->store,
+ $subject
+ );
+
+ $options = [
+ 'Foo' => 42
+ ];
+
+ $instance->setOptions(
+ $options
+ );
+
+ $instance->setOption(
+ 'Bar',
+ 1001
+ );
+
+ $this->assertEquals(
+ 42,
+ $instance->getOption( 'Foo' )
+ );
+
+ $this->assertEquals(
+ 1001,
+ $instance->getOption( 'Bar' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/ValueFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/ValueFormatterTest.php
new file mode 100644
index 00000000..4996bced
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/Browse/ValueFormatterTest.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\Browse;
+
+use SMW\MediaWiki\Specials\Browse\ValueFormatter;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\Browse\ValueFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ValueFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testGetFormattedSubject() {
+
+ $dataItem = \SMW\DIWikiPage::newFromText( 'Foo', SMW_NS_PROPERTY );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getDataItem' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->once() )
+ ->method( 'getLongHTMLText' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItem ) );
+
+ $this->assertInternalType(
+ 'string',
+ ValueFormatter::getFormattedSubject( $dataValue )
+ );
+ }
+
+ public function testGetFormattedValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->once() )
+ ->method( 'getLongHTMLText' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $propertyValue = $this->getMockBuilder( '\SMWPropertyValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInternalType(
+ 'string',
+ ValueFormatter::getFormattedValue( $dataValue, $propertyValue )
+ );
+ }
+
+ public function testGetPropertyLabel() {
+
+ $propertyValue = $this->getMockBuilder( '\SMWPropertyValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyValue->expects( $this->once() )
+ ->method( 'isVisible' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyValue->expects( $this->once() )
+ ->method( 'getShortHTMLText' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->assertInternalType(
+ 'string',
+ ValueFormatter::getPropertyLabel( $propertyValue )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PageProperty/PageBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PageProperty/PageBuilderTest.php
new file mode 100644
index 00000000..6cdeeb28
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PageProperty/PageBuilderTest.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\PageProperty;
+
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Specials\PageProperty\PageBuilder;
+use SMW\Options;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\PageProperty\PageBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PagePropertyTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $htmlFormRenderer;
+ private $options;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->options = new options();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PageBuilder::class,
+ new PageBuilder( $this->htmlFormRenderer, $this->options )
+ );
+ }
+
+ public function testbuildForm() {
+
+ $methods = [
+ 'setName',
+ 'withFieldset',
+ 'addHorizontalRule',
+ 'openElement',
+ 'closeElement',
+ 'addNonBreakingSpace',
+ 'addInputField',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addPaging',
+ 'addSubmitButton'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'renderForm' );
+
+ $instance = new PageBuilder(
+ $this->htmlFormRenderer,
+ $this->options
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->buildForm()
+ );
+ }
+
+ public function testbuildHtml_Empty() {
+
+ $instance = new PageBuilder(
+ $this->htmlFormRenderer,
+ $this->options
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->buildHtml( [] )
+ );
+ }
+
+ public function testbuildHtml_WithResult() {
+
+ $this->options->set( 'limit', 20 );
+ $this->options->set( 'property', 'Bar' );
+
+ $instance = new PageBuilder(
+ $this->htmlFormRenderer,
+ $this->options
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->buildHtml( [ DIWikiPage::newFromText( 'Foo' ) ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PropertyLabelSimilarity/ContentsBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PropertyLabelSimilarity/ContentsBuilderTest.php
new file mode 100644
index 00000000..04bbf7fd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/PropertyLabelSimilarity/ContentsBuilderTest.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\PropertyLabelSimilarity;
+
+use SMW\MediaWiki\Specials\PropertyLabelSimilarity\ContentsBuilder;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\PropertyLabelSimilarity\ContentsBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ContentsBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $propertyLabelSimilarityLookup;
+ private $htmlFormRenderer;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->propertyLabelSimilarityLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\PropertyLabelSimilarityLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->htmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ContentsBuilder::class,
+ new ContentsBuilder( $this->propertyLabelSimilarityLookup, $this->htmlFormRenderer )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $requestOptions = $this->getMockBuilder( '\SMW\RequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $requestOptions->expects( $this->atLeastOnce() )
+ ->method( 'getExtraConditions' )
+ ->will( $this->returnValue( [ 'type' => 'Foo', 'threshold' => 50 ] ) );
+
+ $methods = [
+ 'setName',
+ 'setMethod',
+ 'addHiddenField',
+ 'addHeader',
+ 'addParagraph',
+ 'addSubmitButton',
+ 'withFieldset',
+ 'addInputField',
+ 'addNonBreakingSpace',
+ 'addCheckbox',
+ 'addQueryParameter',
+ 'addPaging'
+ ];
+
+ foreach ( $methods as $method ) {
+ $this->htmlFormRenderer->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnSelf() );
+ }
+
+ $this->htmlFormRenderer->expects( $this->atLeastOnce() )
+ ->method( 'getForm' );
+
+ $instance = new ContentsBuilder(
+ $this->propertyLabelSimilarityLookup,
+ $this->htmlFormRenderer
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml( $requestOptions )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageBuilderTest.php
new file mode 100644
index 00000000..7862a883
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageBuilderTest.php
@@ -0,0 +1,178 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\SearchByProperty;
+
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\MediaWiki\Renderer\HtmlFormRenderer;
+use SMW\MediaWiki\Specials\SearchByProperty\PageBuilder;
+use SMW\MediaWiki\Specials\SearchByProperty\PageRequestOptions;
+use SMW\MediaWiki\Specials\SearchByProperty\QueryResultLookup;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SearchByProperty\PageBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PageBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+ private $localizer;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+ $this->localizer = Localizer::getInstance();
+ }
+
+ public function testCanConstruct() {
+
+ $HtmlFormRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\HtmlFormRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $PageRequestOptions = $this->getMockBuilder( '\SMW\MediaWiki\Specials\SearchByProperty\PageRequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $QueryResultLookup = $this->getMockBuilder( '\SMW\MediaWiki\Specials\SearchByProperty\QueryResultLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SearchByProperty\PageBuilder',
+ new PageBuilder( $HtmlFormRenderer, $PageRequestOptions, $QueryResultLookup )
+ );
+ }
+
+ public function testGetHtmlForExactValueSearch() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->any() )
+ ->method( 'numParams' )
+ ->will( $this->returnSelf() );
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageBuilder->expects( $this->any() )
+ ->method( 'getMessage' )
+ ->will( $this->returnValue( $message ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [
+ new DIWikiPage( 'ResultOne', NS_MAIN ),
+ new DIWikiPage( 'ResultTwo', NS_HELP ) ] ) );
+
+ $instance = new PageBuilder(
+ new HtmlFormRenderer( $title, $messageBuilder ),
+ new PageRequestOptions( 'Foo/Bar', [] ),
+ new QueryResultLookup( $store )
+ );
+
+ $expected = [
+ 'value="Foo"',
+ 'value="Bar"',
+ 'title="ResultOne',
+ 'title="' . $this->localizer->getNamespaceTextById( NS_HELP ) . ':ResultTwo'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testGetHtmlForNearbyResultsSearch() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message = $this->getMockBuilder( '\Message' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $message->expects( $this->any() )
+ ->method( 'numParams' )
+ ->will( $this->returnSelf() );
+
+ $message->expects( $this->any() )
+ ->method( 'rawParams' )
+ ->will( $this->returnSelf() );
+
+ $messageBuilder = $this->getMockBuilder( '\SMW\MediaWiki\MessageBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageBuilder->expects( $this->any() )
+ ->method( 'getMessage' )
+ ->will( $this->returnValue( $message ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getNext' )
+ ->will( $this->returnValue( false ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [
+ new DIWikiPage( 'ResultOne', NS_MAIN ),
+ new DIWikiPage( 'ResultTwo', NS_HELP ) ] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $requestOptions = [
+ 'propertyString' => 'Foo',
+ 'valueString' => 'Bar',
+ 'nearbySearchForType' => [ '_wpg' ]
+ ];
+
+ $instance = new PageBuilder(
+ new HtmlFormRenderer( $title, $messageBuilder ),
+ new PageRequestOptions( 'Foo/Bar', $requestOptions ),
+ new QueryResultLookup( $store )
+ );
+
+ $expected = [
+ 'value="Foo"',
+ 'value="Bar"',
+ 'title="ResultOne',
+ 'title="' . $this->localizer->getNamespaceTextById( NS_HELP ) . ':ResultTwo'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageRequestOptionsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageRequestOptionsTest.php
new file mode 100644
index 00000000..f7f4336f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/PageRequestOptionsTest.php
@@ -0,0 +1,286 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\SearchByProperty;
+
+use SMW\MediaWiki\Specials\SearchByProperty\PageRequestOptions;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SearchByProperty\PageRequestOptions
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PageRequestOptionsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $queryString = '';
+ $requestOptions = [];
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SearchByProperty\PageRequestOptions',
+ new PageRequestOptions( $queryString, $requestOptions )
+ );
+ }
+
+ /**
+ * @dataProvider pageRequestOptionsProvider
+ */
+ public function testProcess( $queryString, $requestOptions, $expected ) {
+
+ $instance = new PageRequestOptions( $queryString, $requestOptions );
+ $instance->initialize();
+
+ foreach ( $expected as $key => $value ) {
+ $this->assertEquals( $expected[$key], $instance->$key, "$key" );
+ }
+
+ $this->assertInstanceOf(
+ 'SMWPropertyValue',
+ $instance->property
+ );
+ }
+
+ public function pageRequestOptionsProvider() {
+
+ #0
+ $provider[] = [
+ '',
+ [],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'propertyString' => '',
+ 'valueString' => '',
+ 'value' => null
+ ]
+ ];
+
+ #1
+ $provider[] = [
+ 'Foo',
+ [],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'propertyString' => 'Foo',
+ 'valueString' => '',
+ ]
+ ];
+
+ #2
+ $provider[] = [
+ 'Foo_nu/Bar',
+ [],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'propertyString' => 'Foo nu',
+ 'valueString' => 'Bar',
+ 'nearbySearch' => false
+ ]
+ ];
+
+ #3 @see 516
+ $provider[] = [
+ ':Foo("#^$&--2F)/("#^$&-)Bar',
+ [],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'propertyString' => 'Foo("#^$&-/)',
+ 'valueString' => '("#^$&-)Bar',
+ 'nearbySearch' => false
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ 'Foo("#^$&--2F)/("#^$&-)Bar',
+ [
+ 'property' => '("#^$&-/)æŽç§€è‹±',
+ 'value' => '田中("#^$&-)',
+ 'nearbySearchForType' => true
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => false,
+ 'propertyString' => '("#^$&-/)æŽç§€è‹±',
+ 'valueString' => '田中("#^$&-)',
+ ]
+ ];
+
+ #5
+ $provider[] = [
+ '',
+ [
+ 'property' => ' Foo ',
+ 'value' => '',
+ 'nearbySearchForType' => [ '_txt' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => false,
+ 'propertyString' => 'Foo',
+ 'valueString' => '',
+ ]
+ ];
+
+ #6
+ $provider[] = [
+ '',
+ [
+ 'property' => 'Foo',
+ 'value' => '',
+ 'nearbySearchForType' => [ '_wpg' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => true,
+ 'propertyString' => 'Foo',
+ 'valueString' => '',
+ ]
+ ];
+
+ #7
+ $provider[] = [
+ '',
+ [
+ 'property' => '',
+ 'value' => 'Foo',
+ 'nearbySearchForType' => [ '_wpg' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => false,
+ 'propertyString' => '',
+ 'valueString' => 'Foo',
+ ]
+ ];
+
+ #9
+ $provider[] = [
+ '',
+ [
+ 'property' => 'Number',
+ 'value' => '2',
+ 'nearbySearchForType' => [ '_wpg' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => false,
+ 'propertyString' => 'Number',
+ 'valueString' => '2.0',
+ ]
+ ];
+
+ #10
+ $provider[] = [
+ '',
+ [
+ 'property' => 'Temperature',
+ 'value' => '373,15 K',
+ 'nearbySearchForType' => [ '_wpg' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => false,
+ 'propertyString' => 'Temperature',
+ 'valueString' => '373,15 K',
+ ]
+ ];
+
+ #10
+ $provider[] = [
+ ':Temperature/373,15-20K',
+ [
+ 'nearbySearchForType' => [ '_wpg' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => false,
+ 'propertyString' => 'Temperature',
+ 'valueString' => '373,15 K',
+ ]
+ ];
+
+ #11
+ $provider[] = [
+ '',
+ [
+ 'property' => 'Telephone number',
+ 'value' => '%2B1-201-555-0123',
+ 'nearbySearchForType' => [ '_tel' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => true,
+ 'propertyString' => 'Telephone number',
+ 'valueString' => '%2B1-201-555-0123',
+ ]
+ ];
+
+ #11
+ $provider[] = [
+ ':Telephone number/%2B1-2D201-2D555-2D0123',
+ [
+ 'nearbySearchForType' => [ '_tel' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => true,
+ 'propertyString' => 'Telephone number',
+ 'valueString' => '%2B1-201-555-0123',
+ ]
+ ];
+
+ #12
+ $provider[] = [
+ '',
+ [
+ 'property' => 'Text',
+ 'value' => 'abc-123',
+ 'nearbySearchForType' => [ '_txt' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => true,
+ 'propertyString' => 'Text',
+ 'valueString' => 'abc-123',
+ ]
+ ];
+
+ #13
+ $provider[] = [
+ '',
+ [
+ 'property' => 'Text',
+ 'value' => 'foo-123#&^*%<1?=/->"\'',
+ 'nearbySearchForType' => [ '_txt' ]
+ ],
+ [
+ 'limit' => 20,
+ 'offset' => 0,
+ 'nearbySearch' => true,
+ 'propertyString' => 'Text',
+ 'valueString' => 'foo-123#&^*%<1?=/->"\'',
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/QueryResultLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/QueryResultLookupTest.php
new file mode 100644
index 00000000..527c9478
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SearchByProperty/QueryResultLookupTest.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials\SearchByProperty;
+
+use SMW\MediaWiki\Specials\SearchByProperty\PageRequestOptions;
+use SMW\MediaWiki\Specials\SearchByProperty\QueryResultLookup;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SearchByProperty\QueryResultLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class QueryResultLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SearchByProperty\QueryResultLookup',
+ new QueryResultLookup( $store )
+ );
+ }
+
+ public function testDoQueryForNonValue() {
+
+ $pageRequestOptions = new PageRequestOptions( 'Foo', [] );
+ $pageRequestOptions->initialize();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->isType( 'null' ),
+ $this->isInstanceOf( '\SMW\DIProperty' ),
+ $this->anything() )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new QueryResultLookup( $store );
+
+ $this->assertInternaltype(
+ 'array',
+ $instance->doQuery( $pageRequestOptions )
+ );
+ }
+
+ public function testDoQueryForExactValue() {
+
+ $pageRequestOptions = new PageRequestOptions( 'Foo/Bar', [] );
+ $pageRequestOptions->initialize();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->isInstanceOf( '\SMW\DIProperty' ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new QueryResultLookup( $store );
+
+ $this->assertInternaltype(
+ 'array',
+ $instance->doQuery( $pageRequestOptions )
+ );
+ }
+
+ public function testDoQueryForNearbyResults() {
+
+ $pageRequestOptions = new PageRequestOptions( 'Foo/Bar', [] );
+ $pageRequestOptions->initialize();
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getNext' )
+ ->will( $this->returnValue( false ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getQueryResult' )
+ ->with( $this->isInstanceOf( '\SMWQuery' ) )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $instance = new QueryResultLookup( $store );
+
+ $this->assertInternaltype(
+ 'array',
+ $instance->doQueryForNearbyResults( $pageRequestOptions, 1 )
+ );
+ }
+
+ public function testDoQueryLinksReferences() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getId' ] )
+ ->getMock();
+
+ $idTable->expects( $this->atLeastOnce() )
+ ->method( 'getId' )
+ ->will( $this->onConsecutiveCalls( 42 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $pageRequestOptions = new PageRequestOptions( 'Foo/Bar', [] );
+ $pageRequestOptions->initialize();
+
+ $instance = new QueryResultLookup( $store );
+
+ $this->assertInternaltype(
+ 'array',
+ $instance->doQueryLinksReferences( $pageRequestOptions, 1 )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAdminTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAdminTest.php
new file mode 100644
index 00000000..77b42be9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAdminTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\MediaWiki\Specials\SpecialAdmin;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialAdmin
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SpecialAdminTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SpecialAdmin',
+ new SpecialAdmin()
+ );
+ }
+
+ public function testExecuteWithValidUser() {
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' );
+
+ $query = '';
+ $instance = new SpecialAdmin();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SemanticMadiaWiki' )
+ );
+
+ $oldOutput = $instance->getOutput();
+
+ $instance->getContext()->setOutput( $outputPage );
+ $instance->getContext()->setUser( new MockSuperUser() );
+
+ $instance->execute( $query );
+
+ // Context is static avoid any succeeding tests to fail
+ $instance->getContext()->setOutput( $oldOutput );
+ }
+
+ public function testExecuteWithInvalidPermissionThrowsException() {
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = '';
+ $instance = new SpecialAdmin();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SemanticMadiaWiki' )
+ );
+
+ $instance->getContext()->setUser( $user );
+
+ $this->setExpectedException( 'PermissionsError' );
+ $instance->execute( $query );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAskTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAskTest.php
new file mode 100644
index 00000000..1eea2f73
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialAskTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\MediaWiki\Specials\SpecialAsk;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialAsk
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SpecialAskTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SpecialAsk',
+ new SpecialAsk()
+ );
+ }
+
+ public function testExecuteWithValidUser() {
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' );
+
+ $query = '';
+ $instance = new SpecialAsk();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SemanticMadiaWiki' )
+ );
+
+ $oldOutput = $instance->getOutput();
+
+ $instance->getContext()->setOutput( $outputPage );
+ $instance->getContext()->setUser( new MockSuperUser() );
+
+ $instance->execute( $query );
+
+ // Context is static avoid any succeeding tests to fail
+ $instance->getContext()->setOutput( $oldOutput );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialBrowseTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialBrowseTest.php
new file mode 100644
index 00000000..e12cad78
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialBrowseTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\MediaWiki\Specials\SpecialBrowse;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialBrowse
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SpecialBrowseTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment( [
+ 'smwgBrowseFeatures' => SMW_BROWSE_SHOW_INCOMING | SMW_BROWSE_USE_API
+ ] );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ $this->stringValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider queryParameterProvider
+ */
+ public function testQueryParameter( $query, $expected ) {
+
+ $instance = new SpecialBrowse();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SpecialBrowse' )
+ );
+
+ $instance->execute( $query );
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getOutput()->getHtml()
+ );
+ }
+
+ public function queryParameterProvider() {
+
+ #0
+ $provider[] = [
+ '',
+ [ 'smw-callout smw-callout-error' ]
+ ];
+
+ #1
+ $provider[] = [
+ ':Has-20foo/http:-2F-2Fexample.org-2Fid-2FCurly-2520Brackets-257B-257D',
+ [ 'smw-callout smw-callout-error' ]
+ ];
+
+ #2
+ $provider[] = [
+ 'Foo/Bar',
+ [
+ 'data-subject="Foo/Bar#0##"',
+ 'data-options="{&quot;dir&quot;:null,&quot;group&quot;:null,&quot;printable&quot;:null,&quot;offset&quot;:null,&quot;including&quot;:null,&quot;showInverse&quot;:false,&quot;showAll&quot;:true,&quot;showGroup&quot;:false,&quot;showSort&quot;:false,&quot;api&quot;:true,&quot;valuelistlimit.out&quot;:&quot;200&quot;,&quot;valuelistlimit.in&quot;:&quot;20&quot;}"'
+ ]
+ ];
+
+ #3
+ $provider[] = [
+ ':Main-20Page-23_QUERY140d50d705e9566904fc4a877c755964',
+ [
+ 'data-subject="Main_Page#0##_QUERY140d50d705e9566904fc4a877c755964"',
+ 'data-options="{&quot;dir&quot;:null,&quot;group&quot;:null,&quot;printable&quot;:null,&quot;offset&quot;:null,&quot;including&quot;:null,&quot;showInverse&quot;:false,&quot;showAll&quot;:true,&quot;showGroup&quot;:false,&quot;showSort&quot;:false,&quot;api&quot;:true,&quot;valuelistlimit.out&quot;:&quot;200&quot;,&quot;valuelistlimit.in&quot;:&quot;20&quot;}"'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialDeferredRequestDispatcherTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialDeferredRequestDispatcherTest.php
new file mode 100644
index 00000000..14773fb5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialDeferredRequestDispatcherTest.php
@@ -0,0 +1,197 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Specials\SpecialDeferredRequestDispatcher;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialDeferredRequestDispatcher
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class SpecialDeferredRequestDispatcherTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+ private $stringValidator;
+ private $spyLogger;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyLogger = $this->testEnvironment->newSpyLogger();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertySubjects' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->setOption( 'smwgSemanticsEnabled', true );
+ $store->setOption( 'smwgAutoRefreshSubject', true );
+
+ $store->setLogger( $this->spyLogger );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->stringValidator = $this->testEnvironment->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SpecialDeferredRequestDispatcher',
+ new SpecialDeferredRequestDispatcher()
+ );
+ }
+
+ public function testGetTargetURL() {
+
+ $this->assertContains(
+ ':DeferredRequestDispatcher',
+ SpecialDeferredRequestDispatcher::getTargetURL()
+ );
+ }
+
+ public function testgetRequestToken() {
+
+ $this->assertInternalType(
+ 'string',
+ SpecialDeferredRequestDispatcher::getRequestToken( 'Foo' )
+ );
+
+ $this->assertNotSame(
+ SpecialDeferredRequestDispatcher::getRequestToken( 'Bar' ),
+ SpecialDeferredRequestDispatcher::getRequestToken( 'Foo' )
+ );
+ }
+
+ public function testValidPostAsyncUpdateJob() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( "Skipping test because of missing method" );
+ }
+
+ $timestamp = time();
+
+ $parameters = json_encode( [
+ 'async-job' => [ 'type' => 'SMW\UpdateJob', 'title' => 'Foo' ],
+ 'timestamp' => $timestamp,
+ 'requestToken' => SpecialDeferredRequestDispatcher::getRequestToken( $timestamp ),
+ ] );
+
+ $instance = new SpecialDeferredRequestDispatcher();
+ $instance->disallowToModifyHttpHeader();
+
+ $instance->getContext()->setRequest(
+ new \FauxRequest( [ 'parameters' => $parameters ], true )
+ );
+
+ $this->assertTrue(
+ $instance->execute( '' )
+ );
+ }
+
+ public function testValidPostAsyncParserCachePurgeJob() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( "Skipping test because of missing method" );
+ }
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertySubjects' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->setLogger( $this->spyLogger );
+
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $timestamp = time();
+
+ $parameters = json_encode( [
+ 'async-job' => [ 'type' => 'SMW\ParserCachePurgeJob', 'title' => 'Foo' ],
+ 'timestamp' => $timestamp,
+ 'requestToken' => SpecialDeferredRequestDispatcher::getRequestToken( $timestamp ),
+ 'idlist' => [ 1, 2 ]
+ ] );
+
+ $instance = new SpecialDeferredRequestDispatcher();
+ $instance->disallowToModifyHttpHeader();
+
+ $instance->getContext()->setRequest(
+ new \FauxRequest( [ 'parameters' => $parameters ], true )
+ );
+
+ $this->assertTrue(
+ $instance->execute( '' )
+ );
+ }
+
+ public function testInvalidPostRequestToken() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( "Skipping test because of missing method" );
+ }
+
+ $timestamp = time();
+
+ $parameters = json_encode( [
+ 'timestamp' => $timestamp,
+ 'requestToken' => SpecialDeferredRequestDispatcher::getRequestToken( 'Foo' )
+ ] );
+
+ $instance = new SpecialDeferredRequestDispatcher();
+ $instance->disallowToModifyHttpHeader();
+
+ $instance->getContext()->setRequest(
+ new \FauxRequest( [ 'parameters' => $parameters ], true )
+ );
+
+ $this->assertNull(
+ $instance->execute( '' )
+ );
+ }
+
+ public function testGetRequestForAsyncJob() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ) {
+ $this->markTestSkipped( "Skipping test because of missing method" );
+ }
+
+ $request = [];
+
+ $instance = new SpecialDeferredRequestDispatcher();
+ $instance->disallowToModifyHttpHeader();
+
+ $instance->getContext()->setRequest(
+ new \FauxRequest( $request, false )
+ );
+
+ $this->assertNull(
+ $instance->execute( '' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPagePropertyTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPagePropertyTest.php
new file mode 100644
index 00000000..e391b938
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPagePropertyTest.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\MediaWiki\Specials\SpecialPageProperty;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialPageProperty
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SpecialPagePropertyTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyValues' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ $this->stringValidator = $this->testEnvironment->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SpecialPageProperty',
+ new SpecialPageProperty()
+ );
+ }
+
+ /**
+ * @dataProvider queryParameterProvider
+ */
+ public function testQueryParameter( $query, $expected ) {
+
+ $instance = new SpecialPageProperty();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'PageProperty' )
+ );
+
+ $instance->execute( $query );
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getOutput()->getHtml()
+ );
+ }
+
+ public function testRequestParameter() {
+
+ $request = [
+ 'type' => 'Has subobject',
+ 'from' => 'Bar'
+ ];
+
+ $expected = [
+ 'value="Has subobject"', 'value="Bar"'
+ ];
+
+ $instance = new SpecialPageProperty();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'PageProperty' )
+ );
+
+ $instance->getContext()->setRequest(
+ new \FauxRequest( $request, true )
+ );
+
+ $instance->execute( null );
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getOutput()->getHtml()
+ );
+ }
+
+ public function queryParameterProvider() {
+
+ #0
+ $provider[] = [
+ 'Has page::Has prop',
+ [ 'type=Has+prop', 'from=Has+page' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialProcessingErrorListTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialProcessingErrorListTest.php
new file mode 100644
index 00000000..9f6943a2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialProcessingErrorListTest.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\MediaWiki\Specials\SpecialProcessingErrorList;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialProcessingErrorList
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SpecialProcessingErrorListTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ $this->stringValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanExecute() {
+
+ $instance = new SpecialProcessingErrorList();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SpecialProcessingErrorList' )
+ );
+
+ $this->assertTrue(
+ $instance->execute( '' )
+ );
+ }
+
+ public function testGetLocalAskRedirectUrl() {
+
+ $instance = new SpecialProcessingErrorList();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SpecialProcessingErrorList' )
+ );
+
+ $expected = [
+ '%5B%5BHas+processing+error+text%3A%3A%2B%5D%5D',
+ '&po=%3FHas+improper+value+for%7C%3FHas+processing+error+text',
+ '&p=class%3Dsortable-20wikitable-20smwtable-2Dstriped',
+ '&eq=no&limit=5',
+ '&bTitle=processingerrorlist',
+ '&bMsg=smw-processingerrorlist-intro'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getLocalAskRedirectUrl( 5 )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPropertyLabelSimilarityTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPropertyLabelSimilarityTest.php
new file mode 100644
index 00000000..d7a5c3df
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialPropertyLabelSimilarityTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\MediaWiki\Specials\SpecialPropertyLabelSimilarity;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialPropertyLabelSimilarity
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SpecialPropertyLabelSimilarityTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ $this->stringValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanExecute() {
+
+ $instance = new SpecialPropertyLabelSimilarity();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SpecialPropertyLabelSimilarity' )
+ );
+
+ $this->assertTrue(
+ $instance->execute( '' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialSearchByPropertyTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialSearchByPropertyTest.php
new file mode 100644
index 00000000..4df56790
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialSearchByPropertyTest.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Specials\SpecialSearchByProperty;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialSearchByProperty
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SpecialSearchByPropertyTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+
+ $propertyTableIdReferenceFinder = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableIdReferenceFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyTableIdReferenceFinder', 'getPropertyValues', 'getPropertySubjects' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTableIdReferenceFinder' )
+ ->will( $this->returnValue( $propertyTableIdReferenceFinder ) );
+
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Specials\SpecialSearchByProperty',
+ new SpecialSearchByProperty()
+ );
+ }
+
+ /**
+ * @dataProvider queryParameterProvider
+ */
+ public function testQueryParameter( $query, $expected ) {
+
+ $instance = new SpecialSearchByProperty();
+ $instance->getContext()->setTitle( Title::newFromText( 'SearchByProperty' ) );
+
+ $instance->execute( $query );
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getOutput()->getHtml()
+ );
+ }
+
+ public function testXRequestParameter() {
+
+ $request = [
+ 'x' => ':Has-20subobject/Foo-23%7B%7D'
+ ];
+
+ $expected = [
+ 'property=Has+subobject', 'value=Foo%23%257B%257D'
+ ];
+
+ $instance = new SpecialSearchByProperty();
+ $instance->getContext()->setTitle( Title::newFromText( 'SearchByProperty' ) );
+ $instance->getContext()->setRequest( new \FauxRequest( $request, true ) );
+
+ $instance->execute( null );
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getOutput()->getHtml()
+ );
+ }
+
+ public function queryParameterProvider() {
+
+ #0
+ $provider[] = [
+ 'Foo/Bar',
+ [ 'property=Foo', 'value=Bar' ]
+ ];
+
+ #1
+ $provider[] = [
+ ':Has-20foo/http:-2F-2Fexample.org-2Fid-2FCurly-2520Brackets-257B-257D',
+ [ 'property=Has+foo', 'value=http%3A%2F%2Fexample.org%2Fid%2FCurly%2520Brackets%257B%257D' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialURIResolverTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialURIResolverTest.php
new file mode 100644
index 00000000..6e9e92d7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/Specials/SpecialURIResolverTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\MediaWiki\Specials;
+
+use SMW\MediaWiki\Specials\SpecialURIResolver;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\Specials\SpecialURIResolver
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SpecialURIResolverTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testExecuteOnEmptyContext() {
+
+ $instance = new SpecialURIResolver();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SpecialURIResolver' )
+ );
+
+ $instance->execute( '' );
+
+ $this->assertContains(
+ 'https://www.w3.org/2001/tag/issues.html#httpRange-14',
+ $instance->getOutput()->getHTML()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/StripMarkerDecoderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/StripMarkerDecoderTest.php
new file mode 100644
index 00000000..73f77e1b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/StripMarkerDecoderTest.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\StripMarkerDecoder;
+use Title;
+
+/**
+ * @covers \SMW\MediaWiki\StripMarkerDecoder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class StripMarkerDecoderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $stripState = $this->getMockBuilder( '\StripState' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ StripMarkerDecoder::class,
+ new StripMarkerDecoder( $stripState )
+ );
+ }
+
+ public function testIsSupported() {
+
+ $stripState = $this->getMockBuilder( '\StripState' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new StripMarkerDecoder(
+ $stripState
+ );
+
+ $instance->isSupported( true );
+
+ $this->assertTrue(
+ $instance->canUse()
+ );
+ }
+
+ public function testDecodeWithoutStrip() {
+
+ $stripState = $this->getMockBuilder( '\StripState' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new StripMarkerDecoder(
+ $stripState
+ );
+
+ $instance->isSupported( true );
+
+ $this->assertEquals(
+ '<pre>Foo</pre>',
+ $instance->decode( '<pre>Foo</pre>' )
+ );
+ }
+
+ public function testUnstripNoWiki() {
+
+ $stripState = $this->getMockBuilder( '\StripState' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stripState->expects( $this->once() )
+ ->method( 'unstripNoWiki' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new StripMarkerDecoder(
+ $stripState
+ );
+
+ $this->assertEquals(
+ '&lt;nowiki&gt;&lt;pre&gt;Foo&lt;/pre&gt;&lt;/nowiki&gt;',
+ $instance->unstrip( '<pre>Foo</pre>' )
+ );
+ }
+
+ public function testUnstripGeneral() {
+
+ $stripState = $this->getMockBuilder( '\StripState' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stripState->expects( $this->once() )
+ ->method( 'unstripNoWiki' )
+ ->will( $this->returnValue( '' ) );
+
+ $stripState->expects( $this->once() )
+ ->method( 'unstripGeneral' );
+
+ $instance = new StripMarkerDecoder(
+ $stripState
+ );
+
+ $instance->isSupported( true );
+
+ $instance->unstrip( '<pre>Foo</pre>' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleFactoryTest.php
new file mode 100644
index 00000000..2e17196d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleFactoryTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\TitleFactory;
+
+/**
+ * @covers \SMW\MediaWiki\TitleFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class TitleFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TitleFactory::class,
+ new TitleFactory()
+ );
+ }
+
+ public function testCreateTitleFromText() {
+
+ $instance = new TitleFactory();
+
+ $this->assertInstanceOf(
+ '\Title',
+ $instance->newFromText( __METHOD__ )
+ );
+ }
+
+ public function testNewFromID() {
+
+ $instance = new TitleFactory();
+ $title = $instance->newFromID( 9999999 );
+
+ $this->assertTrue(
+ $title === null || $title instanceof \Title
+ );
+ }
+
+ public function testNewFromIDs() {
+
+ $instance = new TitleFactory();
+
+ $this->assertInternalType(
+ 'array',
+ $instance->newFromIDs( [ 9999999 ] )
+ );
+ }
+
+ public function testMakeTitleSafe() {
+
+ $instance = new TitleFactory();
+
+ $this->assertInstanceOf(
+ '\Title',
+ $instance->makeTitleSafe( NS_MAIN, 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleLookupTest.php
new file mode 100644
index 00000000..c9185bf4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MediaWiki/TitleLookupTest.php
@@ -0,0 +1,258 @@
+<?php
+
+namespace SMW\Tests\MediaWiki;
+
+use SMW\MediaWiki\TitleLookup;
+use Title;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\MediaWiki\TitleLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class TitleLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\TitleLookup',
+ new TitleLookup( $database )
+ );
+ }
+
+ public function testSelectAllOnCategoryNamespace() {
+
+ $row = new \stdClass;
+ $row->cat_title = 'Foo';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->stringContains( 'category' ),
+ $this->anything(),
+ $this->anything(),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertArrayOfTitles(
+ $instance->setNamespace( NS_CATEGORY )->selectAll()
+ );
+ }
+
+ public function testSelectAllOnMainNamespace() {
+
+ $row = new \stdClass;
+ $row->page_namespace = NS_MAIN;
+ $row->page_title = 'Bar';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'page_namespace' => NS_MAIN ] ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertArrayOfTitles(
+ $instance->setNamespace( NS_MAIN )->selectAll()
+ );
+ }
+
+ public function testSelectByRangeOnCategoryNamespace() {
+
+ $row = new \stdClass;
+ $row->cat_title = 'Foo';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->stringContains( 'category' ),
+ $this->anything(),
+ $this->equalTo( [ "cat_id BETWEEN 1 AND 5" ] ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertArrayOfTitles(
+ $instance->setNamespace( NS_CATEGORY )->selectByIdRange( 1, 5 )
+ );
+ }
+
+ public function testSelectByRangeOnMainNamespace() {
+
+ $row = new \stdClass;
+ $row->page_namespace = NS_MAIN;
+ $row->page_title = 'Bar';
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ "page_id BETWEEN 6 AND 10", 'page_namespace' => NS_MAIN ] ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertArrayOfTitles(
+ $instance->setNamespace( NS_MAIN )->selectByIdRange( 6, 10 )
+ );
+ }
+
+ public function testSelectAllOnMainNamespaceWithEmptyResult() {
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with( $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'page_namespace' => NS_MAIN ] ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertArrayOfTitles(
+ $instance->setNamespace( NS_MAIN )->selectAll()
+ );
+ }
+
+ public function testSelectAllRedirectPages() {
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->any() )
+ ->method( 'select' )
+ ->with(
+ $this->equalTo( [ 'page', 'redirect' ] ),
+ $this->anything(),
+ $this->anything(),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertArrayOfTitles(
+ $instance->getRedirectPages()
+ );
+ }
+
+ public function testMaxIdForMainNamespace() {
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->once() )
+ ->method( 'selectField' )
+ ->with( $this->equalTo( 'page' ),
+ $this->anything(),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( 9999 ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertEquals(
+ 9999,
+ $instance->setNamespace( NS_MAIN )->getMaxId()
+ );
+ }
+
+ public function testgetMaxIdForCategoryNamespace() {
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->once() )
+ ->method( 'selectField' )
+ ->with( $this->equalTo( 'category' ),
+ $this->anything(),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( 1111 ) );
+
+ $instance = new TitleLookup( $database );
+
+ $this->assertEquals(
+ 1111,
+ $instance->setNamespace( NS_CATEGORY )->getMaxId()
+ );
+ }
+
+ public function testSelectAllOnMissingNamespaceThrowsException() {
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new TitleLookup( $database );
+ $instance->selectAll();
+ }
+
+ public function testSelectByRangeOnMissingNamespaceThrowsException() {
+
+ $this->setExpectedException( 'RuntimeException' );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new TitleLookup( $database );
+ $instance->selectByIdRange( 1, 5 );
+ }
+
+ protected function assertArrayOfTitles( $arrayOfTitles ) {
+
+ $this->assertInternalType( 'array', $arrayOfTitles );
+
+ foreach ( $arrayOfTitles as $title ) {
+ $this->assertInstanceOf( 'Title', $title );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MessageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MessageTest.php
new file mode 100644
index 00000000..45ba9291
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/MessageTest.php
@@ -0,0 +1,211 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Message;
+
+/**
+ * @covers \SMW\Message
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class MessageTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ public function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->resetPoolCacheById( Message::POOLCACHE_ID );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Message',
+ new Message()
+ );
+ }
+
+ public function testEmptyStringOnUnregisteredHandler() {
+
+ $instance = new Message();
+
+ $this->assertEmpty(
+ $instance->get( 'Foo', 'Foo' )
+ );
+ }
+
+ public function testRegisteredHandler() {
+
+ $instance = new Message();
+
+ $instance->registerCallbackHandler( 'Foo', function( $parameters, $language ) {
+
+ if ( $parameters[0] === 'Foo' && $language === Message::CONTENT_LANGUAGE ) {
+ return 'Foobar';
+ }
+
+ if ( $parameters[0] === 'Foo' && is_string( $language ) ) {
+ return $language;
+ }
+
+ return 'UNKNOWN';
+ } );
+
+ $this->assertEquals(
+ 'Foobar',
+ $instance->get( 'Foo', 'Foo' )
+ );
+
+ $this->assertEquals(
+ 'en',
+ $instance->get( 'Foo', 'Foo', 'en' )
+ );
+
+ $instance->deregisterHandlerFor( 'Foo' );
+ }
+
+ public function testRegisteredHandlerWithLanguage() {
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->once() )
+ ->method( 'getCode' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $instanceSpy = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'hasLanguage' ] )
+ ->getMock();
+
+ $instanceSpy->expects( $this->once() )
+ ->method( 'hasLanguage' )
+ ->with( $this->identicalTo( $language ) );
+
+ $instance = new Message();
+ $instance->clear();
+
+ $instance->registerCallbackHandler( 'Foo', function( $parameters, $language ) use ( $instanceSpy ){
+ $instanceSpy->hasLanguage( $language );
+ return 'UNKNOWN';
+ } );
+
+ $instance->get( 'Bar', 'Foo', $language );
+ $instance->deregisterHandlerFor( 'Foo' );
+ }
+
+ public function testFromCache() {
+
+ $instance = new Message();
+ $instance->clear();
+
+ $instance->registerCallbackHandler( 'SimpleText', function( $parameters, $language ) {
+ return 'Foo';
+ } );
+
+ $instance->get( 'Foo', 'SimpleText' );
+
+ $this->assertEquals(
+ [
+ 'inserts' => 1,
+ 'deletes' => 0,
+ 'max' => 1000,
+ 'count' => 1,
+ 'hits' => 0,
+ 'misses' => 1
+ ],
+ $instance->getCache()->getStats()
+ );
+
+ $instance->get( 'Foo', 'SimpleText', 'ooo' );
+
+ $this->assertEquals(
+ [
+ 'inserts' => 2,
+ 'deletes' => 0,
+ 'max' => 1000,
+ 'count' => 2,
+ 'hits' => 0,
+ 'misses' => 2
+ ],
+ $instance->getCache()->getStats()
+ );
+
+ // Repeated request
+ $instance->get( 'Foo', 'SimpleText' );
+
+ $this->assertEquals(
+ [
+ 'inserts' => 2,
+ 'deletes' => 0,
+ 'max' => 1000,
+ 'count' => 2,
+ 'hits' => 1,
+ 'misses' => 2
+ ],
+ $instance->getCache()->getStats()
+ );
+
+ $instance->deregisterHandlerFor( 'SimpleText' );
+ }
+
+ /**
+ * @dataProvider encodeProvider
+ */
+ public function testEncode( $string, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ Message::encode( $string )
+ );
+ }
+
+ public function testDecode() {
+
+ $this->assertEquals(
+ false,
+ Message::decode( 'Foo' )
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ Message::decode( '[2,"Foo"]' )
+ );
+ }
+
+ public function encodeProvider() {
+
+ $provider[] = [
+ 'Foo',
+ '[2,"Foo"]'
+ ];
+
+ $provider[] = [
+ [ 'Foo' ],
+ '[2,"Foo"]'
+ ];
+
+ $provider[] = [
+ '[2,"Foo"]',
+ '[2,"Foo"]'
+ ];
+
+ $provider[] = [
+ [ 'Foo', '<strong>Expression error: Unrecognized word "yyyy".</strong>' ],
+ '[2,"Foo","Expression error: Unrecognized word \"yyyy\"."]'
+ ];
+
+ $provider[] = [
+ [ 'eb0afd6194bab91b6d32d2db4bb30060' => '[2,"smw-datavalue-wikipage-invalid-title","Help:"]' ],
+ '[2,"smw-datavalue-wikipage-invalid-title","Help:"]'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceExaminerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceExaminerTest.php
new file mode 100644
index 00000000..1ce9d3c0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceExaminerTest.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\NamespaceExaminer;
+
+/**
+ * @covers \SMW\NamespaceExaminer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class NamespaceExaminerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\NamespaceExaminer',
+ new NamespaceExaminer( [] )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\NamespaceExaminer',
+ NamespaceExaminer::newFromArray( [] )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\NamespaceExaminer',
+ NamespaceExaminer::getInstance()
+ );
+ }
+
+ public function testIsSemanticEnabled() {
+
+ $instance = new NamespaceExaminer( [ NS_MAIN => true ] );
+
+ $this->assertTrue(
+ $instance->isSemanticEnabled( NS_MAIN )
+ );
+
+ $instance = new NamespaceExaminer( [ NS_MAIN => false ] );
+
+ $this->assertFalse(
+ $instance->isSemanticEnabled( NS_MAIN )
+ );
+ }
+
+ public function testNoNumberNamespaceThrowsException() {
+
+ $instance = new NamespaceExaminer( [ NS_MAIN => true ] );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->isSemanticEnabled( 'ichi' );
+ }
+
+ /**
+ * Bug 51435; return false instead of an Exception
+ */
+ public function testNoValidNamespaceException() {
+
+ $instance = new NamespaceExaminer( [ NS_MAIN => true ] );
+
+ $this->assertFalse(
+ $instance->isSemanticEnabled( 99991001 )
+ );
+ }
+
+ public function testGetInstance() {
+
+ $instance = NamespaceExaminer::getInstance();
+
+ $this->assertSame(
+ $instance,
+ NamespaceExaminer::getInstance()
+ );
+
+ NamespaceExaminer::clear();
+
+ $this->assertNotSame(
+ $instance,
+ NamespaceExaminer::getInstance()
+ );
+ }
+
+ public function testNewFromArray() {
+
+ $instance = NamespaceExaminer::newFromArray( [ NS_MAIN => true ] );
+
+ $this->assertTrue(
+ $instance->isSemanticEnabled( NS_MAIN )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceManagerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceManagerTest.php
new file mode 100644
index 00000000..14cfdd8a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceManagerTest.php
@@ -0,0 +1,315 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\NamespaceManager;
+
+/**
+ * @covers \SMW\NamespaceManager
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class NamespaceManagerTest extends \PHPUnit_Framework_TestCase {
+
+ private $varsEnvironment;
+ private $lang;
+ private $default;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->lang->expects( $this->any() )
+ ->method( 'fetch' )
+ ->will( $this->returnSelf() );
+
+ $this->lang->expects( $this->any() )
+ ->method( 'getNamespaces' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->lang->expects( $this->any() )
+ ->method( 'getNamespaceAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->default = [
+ 'smwgNamespacesWithSemanticLinks' => [],
+ 'wgNamespacesWithSubpages' => [],
+ 'wgExtraNamespaces' => [],
+ 'wgNamespaceAliases' => [],
+ 'wgContentNamespaces' => [],
+ 'wgNamespacesToBeSearchedDefault' => [],
+ 'wgNamespaceContentModels' => [],
+ 'wgLanguageCode' => 'en'
+ ];
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ NamespaceManager::class,
+ new NamespaceManager( $this->lang )
+ );
+ }
+
+ public function testInitOnIncompleteConfiguration() {
+
+ $vars = $this->default + [
+ 'wgExtraNamespaces' => '',
+ 'wgNamespaceAliases' => ''
+ ];
+
+ $instance = new NamespaceManager( $this->lang );
+ $instance->init( $vars );
+
+ $this->assertNotEmpty(
+ $vars
+ );
+ }
+
+ public function testGetCanonicalNames() {
+
+ $result = NamespaceManager::getCanonicalNames();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $this->assertCount(
+ 8,
+ $result
+ );
+ }
+
+ /**
+ * @dataProvider canonicalNameListProvider
+ */
+ public function testGetCanonicalNameList( $key, $expected ) {
+
+ $result = NamespaceManager::getCanonicalNames();
+
+ $this->assertEquals(
+ $expected,
+ $result[$key]
+ );
+ }
+
+ public function testGetCanonicalNamesWithTypeNamespace() {
+
+ $result = NamespaceManager::getCanonicalNames();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $this->assertCount(
+ 8,
+ $result
+ );
+ }
+
+ public function testBuildNamespaceIndex() {
+ $this->assertInternalType(
+ 'array',
+ NamespaceManager::buildNamespaceIndex( 100 )
+ );
+ }
+
+ public function testInitCustomNamespace() {
+
+ $vars = [
+ 'wgLanguageCode' => 'en',
+ 'wgContentNamespaces' => []
+ ];
+
+ NamespaceManager::initCustomNamespace( $vars );
+
+ $this->assertNotEmpty( $vars );
+
+ $this->assertEquals(
+ 100,
+ $vars['smwgNamespaceIndex']
+ );
+ }
+
+ public function testNamespacesInitWithEmptySettings() {
+
+ $vars = $this->default + [
+ 'wgExtraNamespaces' => '',
+ 'wgNamespaceAliases' => ''
+ ];
+
+ $instance = new NamespaceManager( $this->lang );
+ $instance->init( $vars );
+
+ $this->assertTrue(
+ $vars['smwgNamespacesWithSemanticLinks'][SMW_NS_PROPERTY]
+ );
+
+ $this->assertTrue(
+ $vars['smwgNamespacesWithSemanticLinks'][SMW_NS_CONCEPT]
+ );
+
+ $this->assertTrue(
+ $vars['smwgNamespacesWithSemanticLinks'][SMW_NS_SCHEMA]
+ );
+ }
+
+ public function testInitToKeepPreInitSettings() {
+
+ $vars = $this->default + [
+ 'wgExtraNamespaces' => '',
+ 'wgNamespaceAliases' => '',
+ ];
+
+ $vars['smwgNamespacesWithSemanticLinks'] = [
+ SMW_NS_PROPERTY => false
+ ];
+
+ $instance = new NamespaceManager( $this->lang );
+ $instance->init( $vars );
+
+ $this->assertFalse(
+ $vars['smwgNamespacesWithSemanticLinks'][SMW_NS_PROPERTY]
+ );
+
+ $this->assertTrue(
+ $vars['smwgNamespacesWithSemanticLinks'][SMW_NS_CONCEPT]
+ );
+ }
+
+ public function testInitCustomNamespace_NamespaceAliases() {
+
+ $lang = $this->getMockBuilder( '\SMW\Lang\Lang' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $lang->expects( $this->any() )
+ ->method( 'fetch' )
+ ->will( $this->returnSelf() );
+
+ $lang->expects( $this->any() )
+ ->method( 'getNamespaces' )
+ ->will( $this->returnValue( [] ) );
+
+ $lang->expects( $this->once() )
+ ->method( 'getNamespaceAliases' )
+ ->will( $this->returnValue( [ 'Foo' => SMW_NS_PROPERTY ] ) );
+
+ $vars = $this->default + [
+ 'wgExtraNamespaces' => '',
+ 'wgNamespaceAliases' => '',
+ ];
+
+ $instance = NamespaceManager::initCustomNamespace(
+ $vars,
+ $lang
+ );
+
+ $this->assertArrayHasKey(
+ 'Foo',
+ $vars['wgNamespaceAliases']
+ );
+ }
+
+ public function testInitWithoutOverridingUserSettingsOnExtraNamespaceSettings() {
+
+ $vars = [
+ 'wgNamespacesWithSubpages' => [
+ SMW_NS_PROPERTY => false
+ ],
+ 'wgNamespacesToBeSearchedDefault' => [
+ SMW_NS_PROPERTY => false
+ ],
+ 'wgContentNamespaces' => [
+ SMW_NS_PROPERTY => false
+ ]
+ ] + $this->default;
+
+ $instance = new NamespaceManager( $this->lang );
+ $instance->init( $vars );
+
+ $this->assertFalse(
+ $vars['wgNamespacesWithSubpages'][SMW_NS_PROPERTY]
+ );
+
+ $this->assertFalse(
+ $vars['wgNamespacesToBeSearchedDefault'][SMW_NS_PROPERTY]
+ );
+
+ $this->assertFalse(
+ $vars['wgContentNamespaces'][SMW_NS_PROPERTY]
+ );
+ }
+
+ public function testInit_wgNamespaceContentModels() {
+
+ $vars = $this->default;
+
+ $instance = new NamespaceManager( $this->lang );
+ $instance->init( $vars );
+
+ $this->assertEquals(
+ CONTENT_MODEL_SMW_SCHEMA,
+ $vars['wgNamespaceContentModels'][SMW_NS_SCHEMA]
+ );
+ }
+
+ public function testInitCanonicalNamespacesWithForcedNsReset() {
+
+ $namespaces = [
+ 10001 => 'Property',
+ 10002 => 'Property_talk'
+ ];
+
+ $this->assertTrue(
+ NamespaceManager::initCanonicalNamespaces( $namespaces )
+ );
+
+ $this->assertEquals(
+ 'Property',
+ $namespaces[SMW_NS_PROPERTY]
+ );
+
+ $this->assertEquals(
+ 'Property_talk',
+ $namespaces[SMW_NS_PROPERTY_TALK]
+ );
+ }
+
+ public function canonicalNameListProvider() {
+
+ yield [
+ SMW_NS_PROPERTY,
+ 'Property'
+ ];
+
+ yield [
+ SMW_NS_CONCEPT,
+ 'Concept'
+ ];
+
+ yield [
+ SMW_NS_SCHEMA,
+ 'smw/schema'
+ ];
+
+ yield [
+ SMW_NS_RULE,
+ 'Rule'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceUriFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceUriFinderTest.php
new file mode 100644
index 00000000..60f1f38d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/NamespaceUriFinderTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\NamespaceUriFinder;
+
+/**
+ * @covers \SMW\NamespaceUriFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class NamespaceUriFinderTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider namespaceProvider
+ */
+ public function testGetUriForNamespaceKey( $key, $expected ) {
+ $this->assertInternalType(
+ $expected,
+ NamespaceUriFinder::getUri( $key )
+ );
+ }
+
+ public function namespaceProvider() {
+
+ $provider[] = [
+ 'Foo',
+ 'boolean'
+ ];
+
+ $ns = [
+ 'owl', 'rdf', 'rdfs', 'swivt', 'xsd', 'skos', 'foaf', 'dc',
+ 'OWL'
+ ];
+
+ foreach ( $ns as $key ) {
+ $provider[] = [
+ $key,
+ 'string'
+ ];
+ }
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/OptionsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/OptionsTest.php
new file mode 100644
index 00000000..48d77a8e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/OptionsTest.php
@@ -0,0 +1,233 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Options;
+
+/**
+ * @covers \SMW\Options
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class OptionsTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Options',
+ new Options()
+ );
+ }
+
+ public function testAddOption() {
+
+ $instance = new Options();
+
+ $this->assertFalse(
+ $instance->has( 'Foo' )
+ );
+
+ $instance->set( 'Foo', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->get( 'Foo' )
+ );
+ }
+
+ public function testToArray() {
+
+ $instance = new Options(
+ [ 'Foo' => 42 ]
+ );
+
+ $this->assertEquals(
+ [ 'Foo' => 42 ],
+ $instance->toArray()
+ );
+ }
+
+ public function testUnregisteredKeyThrowsException() {
+
+ $instance = new Options();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->get( 'Foo' );
+ }
+
+ public function testSafeGetOnUnregisteredKey() {
+
+ $instance = new Options();
+
+ $this->assertEquals(
+ 'Default',
+ $instance->safeGet( 'Foo', 'Default' )
+ );
+ }
+
+ public function testFilter() {
+
+ $instance = new Options();
+ $instance->set( 'Foo', '123' );
+ $instance->set( 'Bar', '456' );
+
+ $this->assertEquals(
+ [
+ 'Foo' => '123'
+ ],
+ $instance->filter( [ 'Foo' ] )
+ );
+ }
+
+ /**
+ * @dataProvider dotProvider
+ */
+ public function testDotGet( $options, $key, $expected ) {
+
+ $instance = new Options( $options );
+
+ $this->assertEquals(
+ $expected,
+ $instance->dotGet( $key )
+ );
+ }
+
+ /**
+ * @dataProvider isFlagSetProvider
+ */
+ public function testIsFlagSet( $value, $flag, $expected ) {
+
+ $instance = new Options();
+ $instance->set( 'Foo', $value );
+
+ $this->assertEquals(
+ $expected,
+ $instance->isFlagSet( 'Foo', $flag )
+ );
+ }
+
+ public function isSetProvider() {
+
+ yield [
+ 100,
+ 100,
+ true
+ ];
+
+ yield [
+ 'foo',
+ 'foo',
+ true
+ ];
+
+ yield [
+ ( ( 4 | 8 ) | 16 ),
+ 2,
+ false
+ ];
+
+ yield [
+ 4 | 16,
+ 15,
+ false
+ ];
+
+ yield [
+ false,
+ 2,
+ false
+ ];
+
+ yield [
+ false,
+ false,
+ true
+ ];
+
+ yield [
+ true,
+ true,
+ true
+ ];
+ }
+
+ public function isFlagSetProvider() {
+
+ yield [
+ ( ( 4 | 8 ) | 16 ),
+ 16,
+ true
+ ];
+
+ yield [
+ ( ( 4 | 8 ) | 16 ),
+ 4,
+ true
+ ];
+
+ yield [
+ ( ( 4 | 8 ) | 16 ),
+ 2,
+ false
+ ];
+
+ yield [
+ 4 | 16,
+ 15,
+ false
+ ];
+
+ yield [
+ false,
+ 2,
+ false
+ ];
+ }
+
+ public function dotProvider() {
+
+ $o = [ 'Foo' => [
+ 'Bar' => [ 'Foobar' => 42 ],
+ 'Foobar' => 1001,
+ 'some.other.options' => 9999
+ ],
+ ];
+
+ yield [
+ $o,
+ 'Foo.Bar',
+ [ 'Foobar' => 42 ]
+ ];
+
+ yield [
+ $o,
+ 'Foo.Foobar',
+ 1001
+ ];
+
+ yield [
+ $o,
+ 'Foo.Bar.Foobar',
+ 42
+ ];
+
+ yield [
+ $o,
+ 'Foo.some.other.options',
+ 9999
+ ];
+
+ yield [
+ $o,
+ 'Foo.Bar.Foobar.unkown',
+ false
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ConceptPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ConceptPageTest.php
new file mode 100644
index 00000000..0206a2a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ConceptPageTest.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace SMW\Tests\Page;
+
+use SMW\DIWikiPage;
+use SMW\Page\ConceptPage;
+
+/**
+ * @covers \SMW\Page\ConceptPage
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ConceptPageTest extends \PHPUnit_Framework_TestCase {
+
+ private $title;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $subject = DIWikiPage::newFromText( __METHOD__, SMW_NS_CONCEPT );
+ $this->title = $subject->getTitle();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConceptPage::class,
+ new ConceptPage( $this->title )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ListBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ListBuilderTest.php
new file mode 100644
index 00000000..953d1d82
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ListBuilderTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace SMW\Tests\Page\ListBuilder;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Page\ListBuilder\ListBuilder;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Page\ListBuilder\ListBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ListBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ListBuilder::class,
+ new ListBuilder( $this->store )
+ );
+ }
+
+ public function testCreateEmptyList() {
+
+ $requestOptions = $this->getMockBuilder( '\SMW\RequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ListBuilder( $this->store );
+
+ $property = new DIProperty( 'Foo' );
+ $dataItem = new DIWikiPage( 'Bar', NS_MAIN );
+
+ $this->assertEquals(
+ '',
+ $instance->createHtml( $property, $dataItem, $requestOptions )
+ );
+ }
+
+ public function testCreateHtml() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertySubjects' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertySubjects' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromText( __METHOD__ ) ] ) );
+
+ $requestOptions = $this->getMockBuilder( '\SMW\RequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ListBuilder( $store );
+ $instance->setListLimit( 10 );
+
+ $property = new DIProperty( 'Foo' );
+ $dataItem = new DIWikiPage( 'Bar', NS_MAIN );
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ 'title="SMW\Tests\Page\ListBuilder\ListBuilderTest::testCreateHtml'
+ ],
+ $instance->createHtml( $property, $dataItem, $requestOptions )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ValueListBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ValueListBuilderTest.php
new file mode 100644
index 00000000..8f16755c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilder/ValueListBuilderTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\Page\ListBuilder;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Page\ListBuilder\ValueListBuilder;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Page\ListBuilder\ValueListBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ValueListBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $testEnvironment;
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment( [ 'smwgCompactLinkSupport' => false ] );
+ $this->stringValidator = $this->testEnvironment->newValidatorFactory()->newStringValidator();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ValueListBuilder::class,
+ new ValueListBuilder( $this->store )
+ );
+ }
+
+ public function testCreateEmptyList() {
+
+ $instance = new ValueListBuilder( $this->store );
+
+ $property = new DIProperty( 'Foo' );
+ $dataItem = new DIWikiPage( 'Bar', NS_MAIN );
+
+ $this->assertEquals(
+ '',
+ $instance->createHtml( $property, $dataItem, [] )
+ );
+ }
+
+ public function testCreateHtml() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getAllPropertySubjects', 'getPropertyValues', 'getWikiPageSortKey' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getAllPropertySubjects' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromText( __METHOD__ ) ] ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getWikiPageSortKey' )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromText( 'Bar' ) ] ) );
+
+ $instance = new ValueListBuilder( $store );
+ $instance->setLanguageCode( 'en' );
+
+ $property = new DIProperty( 'Foo' );
+ $dataItem = new DIWikiPage( 'Bar', NS_MAIN );
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ '<div class="smw-table-row header-row"><div class="smw-table-cell header-title"><div id="B">B</div>',
+ 'title="SMW\Tests\Page\ListBuilder\ValueListBuilderTest::testCreateHtml',
+ '<span class="smwsearch">.*:Foo/Bar">+</a>'
+ ],
+ $instance->createHtml( $property, $dataItem, [ 'limit' => 10 ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilderTest.php
new file mode 100644
index 00000000..65a26eec
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/ListBuilderTest.php
@@ -0,0 +1,157 @@
+<?php
+
+namespace SMW\Tests\Page;
+
+use SMW\Page\ListBuilder;
+use SMW\DIWikiPage;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Page\ListBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ListBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $Collator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->collator = $this->getMockBuilder( '\SMW\MediaWiki\Collator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ListBuilder::class,
+ new ListBuilder( $this->store )
+ );
+ }
+
+ public function testGetList() {
+
+ $this->store->expects( $this->once() )
+ ->method( 'getWikiPageSortKey' )
+ ->will( $this->returnValue( 'FOO' ) );
+
+ $this->collator->expects( $this->once() )
+ ->method( 'getFirstLetter' )
+ ->will( $this->returnValue( 'F' ) );
+
+ $instance = new ListBuilder(
+ $this->store,
+ $this->collator
+ );
+
+ $this->assertArrayHasKey(
+ 'F',
+ $instance->getList( [ DIWikiPage::newFromText( 'Foo' ) ] )
+ );
+ }
+
+ public function testGetList_Sorted() {
+
+ $list = [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'ABC' )
+ ];
+
+ $this->store->expects( $this->at( 0 ) )
+ ->method( 'getWikiPageSortKey' )
+ ->will( $this->returnValue( 'FOO' ) );
+
+ $this->collator->expects( $this->at( 0 ) )
+ ->method( 'getFirstLetter' )
+ ->will( $this->returnValue( 'F' ) );
+
+ $this->store->expects( $this->at( 1 ) )
+ ->method( 'getWikiPageSortKey' )
+ ->will( $this->returnValue( 'Abc' ) );
+
+ $this->collator->expects( $this->at( 1 ) )
+ ->method( 'getFirstLetter' )
+ ->will( $this->returnValue( 'A' ) );
+
+ $instance = new ListBuilder(
+ $this->store,
+ $this->collator
+ );
+
+ $this->assertEquals(
+ [ 'A', 'F' ],
+ array_keys( $instance->getList( $list ) )
+ );
+ }
+
+ public function testGetColumnList() {
+
+ $this->store->expects( $this->once() )
+ ->method( 'getWikiPageSortKey' )
+ ->will( $this->returnValue( 'FOO' ) );
+
+ $this->collator->expects( $this->once() )
+ ->method( 'getFirstLetter' )
+ ->will( $this->returnValue( 'F' ) );
+
+ $instance = new ListBuilder(
+ $this->store,
+ $this->collator
+ );
+
+ $instance->setLinker( null );
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $stringValidator->assertThatStringContains(
+ [
+ '<div class="smw-columnlist-container" dir="ltr"><div class="smw-column" style="width:100%;" dir="ltr">',
+ '<div class="smw-column-header">F</div>',
+ '<ul><li>Foo&#160;<span class="smwbrowse">'
+ ],
+ $instance->getColumnList( [ DIWikiPage::newFromText( 'Foo' ) ] )
+ );
+ }
+
+ public function testGetColumnList_ItemFormatter() {
+
+ $this->store->expects( $this->once() )
+ ->method( 'getWikiPageSortKey' )
+ ->will( $this->returnValue( 'FOO' ) );
+
+ $this->collator->expects( $this->once() )
+ ->method( 'getFirstLetter' )
+ ->will( $this->returnValue( 'F' ) );
+
+ $instance = new ListBuilder(
+ $this->store,
+ $this->collator
+ );
+
+ $instance->setItemFormatter( function( $dataValue, $linker ) {
+ return 'Bar';
+ } );
+
+ $stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+
+ $stringValidator->assertThatStringContains(
+ [
+ '<div class="smw-columnlist-container" dir="ltr"><div class="smw-column" style="width:100%;" dir="ltr">',
+ '<ul><li>Bar</li></ul></div>'
+ ],
+ $instance->getColumnList( [ DIWikiPage::newFromText( 'Foo' ) ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PageFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PageFactoryTest.php
new file mode 100644
index 00000000..af5503a5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PageFactoryTest.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace SMW\Tests\Page;
+
+use SMW\Page\PageFactory;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Page\PageFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PageFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PageFactory::class,
+ new PageFactory( $this->store )
+ );
+ }
+
+ public function testNewPageFromNotRegisteredNamespaceThrowsException() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $instance = new PageFactory( $this->store );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->newPageFromTitle( $title );
+ }
+
+ /**
+ * @dataProvider namespaceProvider
+ */
+ public function testNewPageFromTitle( $namespace, $expected ) {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( $namespace ) );
+
+ $instance = new PageFactory( $this->store );
+
+ $this->assertInstanceOf(
+ $expected,
+ $instance->newPageFromTitle( $title )
+ );
+ }
+
+ public function namespaceProvider() {
+
+ $provider[] = [
+ SMW_NS_PROPERTY,
+ 'SMW\Page\PropertyPage'
+ ];
+
+ $provider[] = [
+ SMW_NS_CONCEPT,
+ 'SMW\Page\ConceptPage'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PropertyPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PropertyPageTest.php
new file mode 100644
index 00000000..f7153e93
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Page/PropertyPageTest.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace SMW\Tests\Page;
+
+use SMW\DIWikiPage;
+use SMW\Page\PropertyPage;
+
+/**
+ * @covers \SMW\Page\PropertyPage
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PropertyPageTest extends \PHPUnit_Framework_TestCase {
+
+ private $title;
+ private $store;
+ private $propertySpecificationReqMsgBuilder;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->propertySpecificationReqMsgBuilder = $this->getMockBuilder( '\SMW\PropertySpecificationReqMsgBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->title = DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY )->getTitle();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertyPage::class,
+ new PropertyPage( $this->title, $this->store, $this->propertySpecificationReqMsgBuilder )
+ );
+ }
+
+ public function testGetHtml() {
+
+ $instance = new PropertyPage(
+ $this->title,
+ $this->store,
+ $this->propertySpecificationReqMsgBuilder
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->view()
+ );
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterListDocBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterListDocBuilderTest.php
new file mode 100644
index 00000000..72892ffe
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterListDocBuilderTest.php
@@ -0,0 +1,158 @@
+<?php
+
+namespace SMW\Test;
+
+use ParamProcessor\ParamDefinition;
+use SMW\ParameterListDocBuilder;
+use SMW\Tests\Utils\UtilityFactory;
+use SMW\Tests\Utils\Validators\StringValidator;
+
+/**
+ * @covers SMW\ParameterListDocBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class ParameterListDocBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @var ParameterListDocBuilder
+ */
+ private $builder;
+
+ /**
+ * @var StringValidator
+ */
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+
+ $this->builder = new ParameterListDocBuilder( function( $key ) {
+ return $key;
+ } );
+ }
+
+ public function testGivenNoParameters_noTableIsReturned() {
+ $wikiText = $this->builder->getParameterTable( [] );
+
+ $this->assertSame(
+ '',
+ $wikiText
+ );
+ }
+
+ public function testGivenMinimalParameter_defaultIsRequired() {
+ $wikiText = $this->builder->getParameterTable( [
+ new ParamDefinition( 'number', 'length' )
+ ] );
+
+ $expected = [
+ '{| class="wikitable sortable"',
+ '!validator-describe-header-parameter',
+ '!validator-describe-header-type',
+ '!validator-describe-header-default',
+ '!validator-describe-header-description',
+ '|-',
+ '|length',
+ '|validator-type-number',
+ "|''validator-describe-required''",
+ '|',
+ '|}'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $wikiText
+ );
+ }
+
+ public function testGivenParameterWithDefault_defaultIsListed() {
+ $wikiText = $this->builder->getParameterTable( [
+ new ParamDefinition( 'number', 'length', 42 )
+ ] );
+
+ $expected = [
+ '{| class="wikitable sortable"',
+ '!validator-describe-header-parameter',
+ '!validator-describe-header-type',
+ '!validator-describe-header-default',
+ '!validator-describe-header-description',
+ '|-',
+ '|length',
+ '|validator-type-number',
+ "|42",
+ '|',
+ '|}'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $wikiText
+ );
+ }
+
+ public function testGivenParameterWithAliases_aliasesAreListed() {
+ $paramWithAliases = new ParamDefinition( 'number', 'param-with-alias' );
+ $paramWithAliases->addAliases( 'first-alias', 'second-alias' );
+
+ $paramWithoutAliases = new ParamDefinition( 'string', 'no-aliases' );
+
+ $wikiText = $this->builder->getParameterTable( [ $paramWithAliases, $paramWithoutAliases ] );
+
+ $expected = [
+ '{| class="wikitable sortable"',
+ '!validator-describe-header-parameter',
+ '!validator-describe-header-type',
+ '!validator-describe-header-default',
+ '!validator-describe-header-description',
+ '|-',
+ '|param-with-alias',
+ '|first-alias, second-alias',
+ '|validator-type-number',
+ "|''validator-describe-required''",
+ '|',
+ '|-',
+ '|no-aliases',
+ '| -',
+ '|validator-type-string',
+ "|''validator-describe-required''",
+ '|',
+ '|}'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $wikiText
+ );
+ }
+
+ public function testGivenBooleanParameter_defaultIsListedAsString() {
+ $wikiText = $this->builder->getParameterTable( [
+ new ParamDefinition( 'boolean', 'awesome', true )
+ ] );
+
+ $expected = [
+ '{| class="wikitable sortable"',
+ '!validator-describe-header-parameter',
+ '!validator-describe-header-type',
+ '!validator-describe-header-default',
+ '!validator-describe-header-description',
+ '|-',
+ '|awesome',
+ '|validator-type-boolean',
+ "|yes",
+ '|',
+ '|}'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $wikiText
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterProcessorFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterProcessorFactoryTest.php
new file mode 100644
index 00000000..15e14e5e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParameterProcessorFactoryTest.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ParameterProcessorFactory;
+
+/**
+ * @covers \SMW\ParameterProcessorFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParameterProcessorFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\ParameterProcessorFactory',
+ new ParameterProcessorFactory()
+ );
+ }
+
+ public function testToEliminateFirstParameterIfObject() {
+
+ $parameter = [
+ new \stdClass
+ ];
+
+ $instance = ParameterProcessorFactory::newFromArray( $parameter );
+
+ $this->assertInstanceOf(
+ '\SMW\ParserParameterProcessor',
+ $instance
+ );
+
+ $this->assertEmpty(
+ $instance->getRaw()
+ );
+ }
+
+ public function testNewFromArray() {
+
+ $parameter = [
+ 'La' => 'Lu'
+ ];
+
+ $instance = ParameterProcessorFactory::newFromArray( $parameter );
+
+ $this->assertInstanceOf(
+ '\SMW\ParserParameterProcessor',
+ $instance
+ );
+
+ $this->assertEquals(
+ $parameter,
+ $instance->getRaw()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParametersTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParametersTest.php
new file mode 100644
index 00000000..7cf3b3d1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParametersTest.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Parameters;
+
+/**
+ * @covers \SMW\Parameters
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ParametersTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Parameters::class,
+ new Parameters()
+ );
+ }
+
+ public function testAddOption() {
+
+ $instance = new Parameters();
+
+ $this->assertFalse(
+ $instance->has( 'Foo' )
+ );
+
+ $instance->set( 'Foo', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->get( 'Foo' )
+ );
+ }
+
+ public function testUnregisteredKeyThrowsException() {
+
+ $instance = new Parameters();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->get( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/InTextAnnotationParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/InTextAnnotationParserTest.php
new file mode 100644
index 00000000..6ce96c2d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/InTextAnnotationParserTest.php
@@ -0,0 +1,703 @@
+<?php
+
+namespace SMW\Tests\Parser;
+
+use ParserOutput;
+use ReflectionClass;
+use SMW\DIProperty;
+use SMW\MediaWiki\MagicWordsFinder;
+use SMW\MediaWiki\RedirectTargetFinder;
+use SMW\Parser\InTextAnnotationParser;
+use SMW\Parser\LinksProcessor;
+use SMW\ParserData;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\Parser\InTextAnnotationParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class InTextAnnotationParserTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $testEnvironment;
+ private $linksProcessor;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->linksProcessor = new LinksProcessor();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider textDataProvider
+ */
+ public function testCanConstruct( $namespace ) {
+
+ $parserOutput = $this->getMockBuilder( 'ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $redirectTargetFinder = $this->getMockBuilder( 'SMW\MediaWiki\RedirectTargetFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = Title::newFromText( __METHOD__, $namespace );
+
+ $instance = new InTextAnnotationParser(
+ new ParserData( $title, $parserOutput ),
+ $this->linksProcessor,
+ new MagicWordsFinder(),
+ $redirectTargetFinder
+ );
+
+ $this->assertInstanceOf(
+ InTextAnnotationParser::class,
+ $instance
+ );
+ }
+
+ public function testHasMarker() {
+
+ $this->assertTrue(
+ InTextAnnotationParser::hasMarker( '[[SMW::off]]' )
+ );
+
+ $this->assertTrue(
+ InTextAnnotationParser::hasMarker( '[[SMW::on]]' )
+ );
+
+ $this->assertFalse(
+ InTextAnnotationParser::hasMarker( 'Foo' )
+ );
+ }
+
+ /**
+ * @dataProvider magicWordDataProvider
+ */
+ public function testStripMagicWords( $namespace, $text, array $expected ) {
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__, $namespace ),
+ new ParserOutput()
+ );
+
+ $magicWordsFinder = new MagicWordsFinder( $parserData->getOutput() );
+
+ $instance = new InTextAnnotationParser(
+ $parserData,
+ $this->linksProcessor,
+ $magicWordsFinder,
+ new RedirectTargetFinder()
+ );
+
+ $instance->parse( $text );
+
+ $this->assertEquals(
+ $expected,
+ $magicWordsFinder->getMagicWords()
+ );
+ }
+
+ /**
+ * @dataProvider textDataProvider
+ */
+ public function testTextParse( $namespace, array $settings, $text, array $expected ) {
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__, $namespace ),
+ new ParserOutput()
+ );
+
+ $this->linksProcessor->isStrictMode(
+ isset( $settings['smwgParserFeatures'] ) ? $settings['smwgParserFeatures'] : true
+ );
+
+ $instance = new InTextAnnotationParser(
+ $parserData,
+ $this->linksProcessor,
+ new MagicWordsFinder(),
+ new RedirectTargetFinder()
+ );
+
+ $instance->showErrors(
+ isset( $settings['smwgParserFeatures'] ) ? $settings['smwgParserFeatures'] : true
+ );
+
+ $instance->isLinksInValues(
+ ( ( $settings['smwgParserFeatures'] & SMW_PARSER_LINV ) == SMW_PARSER_LINV )
+ );
+
+ $this->testEnvironment->withConfiguration(
+ $settings
+ );
+
+ $instance->parse( $text );
+
+ $this->assertContains(
+ $expected['resultText'],
+ $text
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testRedirectAnnotationFromText() {
+
+ $namespace = NS_MAIN;
+ $text = '#REDIRECT [[:Lala]]';
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'property' => new DIProperty( '_REDI' ),
+ 'propertyValues' => [ 'Lala' ]
+ ];
+
+ $settings = [
+ 'smwgNamespacesWithSemanticLinks' => [ $namespace => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ];
+
+ $this->testEnvironment->withConfiguration(
+ $settings
+ );
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__, $namespace ),
+ new ParserOutput()
+ );
+
+ $redirectTargetFinder = new RedirectTargetFinder();
+
+ $instance = new InTextAnnotationParser(
+ $parserData,
+ $this->linksProcessor,
+ new MagicWordsFinder(),
+ $redirectTargetFinder
+ );
+
+ $instance->parse( $text );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testRedirectAnnotationFromInjectedRedirectTarget() {
+
+ $namespace = NS_MAIN;
+ $text = '';
+ $redirectTarget = Title::newFromText( 'Foo' );
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'property' => new DIProperty( '_REDI' ),
+ 'propertyValues' => [ 'Foo' ]
+ ];
+
+ $settings = [
+ 'smwgNamespacesWithSemanticLinks' => [ $namespace => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ];
+
+ $this->testEnvironment->withConfiguration(
+ $settings
+ );
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__, $namespace ),
+ new ParserOutput()
+ );
+
+ $redirectTargetFinder = new RedirectTargetFinder();
+
+ $instance = new InTextAnnotationParser(
+ $parserData,
+ $this->linksProcessor,
+ new MagicWordsFinder(),
+ $redirectTargetFinder
+ );
+
+ $instance->setRedirectTarget( $redirectTarget );
+ $instance->parse( $text );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testStripMarkerDecoding() {
+
+ $redirectTargetFinder = $this->getMockBuilder( 'SMW\MediaWiki\RedirectTargetFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stripMarkerDecoder = $this->getMockBuilder( '\SMW\MediaWiki\StripMarkerDecoder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'canUse', 'hasStripMarker', 'unstrip' ] )
+ ->getMock();
+
+ $stripMarkerDecoder->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $stripMarkerDecoder->expects( $this->once() )
+ ->method( 'hasStripMarker' )
+ ->will( $this->returnValue( true ) );
+
+ $stripMarkerDecoder->expects( $this->once() )
+ ->method( 'unstrip' )
+ ->with( $this->stringContains( '<nowiki>Bar</nowiki>' ) )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new InTextAnnotationParser(
+ $parserData,
+ $this->linksProcessor,
+ new MagicWordsFinder(),
+ $redirectTargetFinder
+ );
+
+ $text = '[[Foo::<nowiki>Bar</nowiki>]]';
+
+ $instance->setStripMarkerDecoder( $stripMarkerDecoder );
+ $instance->parse( $text );
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'property' => new DIProperty( 'Foo' ),
+ 'propertyValues' => [ 'Bar' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+
+ $this->assertEquals(
+ '<nowiki>Bar</nowiki>',
+ $text
+ );
+ }
+
+ public function testProcessOnReflection() {
+
+ $parserData = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new InTextAnnotationParser(
+ $parserData,
+ $this->linksProcessor,
+ new MagicWordsFinder(),
+ new RedirectTargetFinder()
+ );
+
+ $reflector = new ReflectionClass( '\SMW\Parser\InTextAnnotationParser' );
+
+ $method = $reflector->getMethod( 'process' );
+ $method->setAccessible( true );
+
+ $result = $method->invoke( $instance, [] );
+ $this->assertEmpty( $result );
+
+ $result = $method->invoke( $instance, [ 'Test::foo', 'SMW' , 'lula' ] );
+ $this->assertEmpty( $result );
+
+ $result = $method->invoke( $instance, [ 'Test::bar', 'SMW' , 'on' ] );
+ $this->assertEmpty( $result );
+
+ $result = $method->invoke( $instance, [ 'Test::lula', 'SMW' , 'off' ] );
+ $this->assertEmpty( $result );
+ }
+
+ /**
+ * @dataProvider stripTextWithAnnotationProvider
+ */
+ public function testStrip( $text, $expectedRemoval, $expectedObscuration ) {
+
+ $this->assertEquals(
+ $expectedRemoval,
+ InTextAnnotationParser::removeAnnotation( $text )
+ );
+
+ $this->assertEquals(
+ $expectedObscuration,
+ InTextAnnotationParser::obfuscateAnnotation( $text )
+ );
+ }
+
+ public function stripTextWithAnnotationProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ 'Suspendisse [[Bar::tincidunt semper|abc]] facilisi',
+ 'Suspendisse abc facilisi',
+ 'Suspendisse &#91;&#91;Bar::tincidunt semper|abc]] facilisi'
+ ];
+
+ return $provider;
+ }
+
+ public function textDataProvider() {
+
+ $testEnvironment = new TestEnvironment();
+ $provider = [];
+
+ // #0 NS_MAIN; [[FooBar...]] with a different caption
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[FooBar::dictumst|寒ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[foo::9001]] et Donec.',
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[:Dictumst|寒ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[:Tincidunt semper|tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[:9001|9001]] et Donec.',
+ 'propertyCount' => 3,
+ 'propertyLabels' => [ 'Foo', 'Bar', 'FooBar' ],
+ 'propertyValues' => [ 'Dictumst', 'Tincidunt semper', '9001' ]
+ ]
+ ];
+
+ // #1 NS_MAIN; [[FooBar...]] with a different caption and enabled SMW_PARSER_LINV
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR | SMW_PARSER_LINV,
+ ],
+ 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[FooBar::dictumst|寒ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::[[tincidunt semper]]]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[foo::[http:://www/foo/9001] ]] et Donec.',
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[:Dictumst|寒ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[:Tincidunt semper|tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis'.
+ ' [[:Http:://www/foo/9001|http:://www/foo/9001]] et Donec.',
+ 'propertyCount' => 3,
+ 'propertyLabels' => [ 'Foo', 'Bar', 'FooBar' ],
+ 'propertyValues' => [ 'Dictumst', 'Tincidunt semper', 'Http:://www/foo/9001' ]
+ ]
+ ];
+
+ // #2 NS_MAIN, [[-FooBar...]] produces an error with inlineErrors = true
+ // (only check for an indication of an error in 'resultText' )
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[-FooBar::dictumst|é‡ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[foo::9001]] et Donec.',
+ [
+ 'resultText' => 'class="smw-highlighter" data-type="4" data-state="inline"',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 3,
+ 'propertyKeys' => [ 'Foo', 'Bar', '_ERRC' ],
+ 'propertyValues' => [ 'Tincidunt semper', '9001' ]
+ ]
+ ];
+
+ // #3 NS_MAIN, [[-FooBar...]] produces an error but inlineErrors = false
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_NONE,
+ ],
+ 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[-FooBar::dictumst|軽ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[foo::9001]] et Donec.',
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' 軽ㄠcursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[:Tincidunt semper|tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[:9001|9001]] et Donec.',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 3,
+ 'propertyKeys ' => [ 'Foo', 'Bar', '_ERRC' ],
+ 'propertyValues' => [ 'Tincidunt semper', '9001' ]
+ ]
+ ];
+
+ // #4 NS_HELP disabled
+ $provider[] = [
+ NS_HELP,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_HELP => false ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[FooBar::dictumst|ãŠã‚‚ã‚ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[Bar::tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[foo::9001]] et Donec.',
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' [[:Dictumst|ãŠã‚‚ã‚ã„]] cursus. Nisl sit condimentum Quisque facilisis' .
+ ' Suspendisse [[:Tincidunt semper|tincidunt semper]] facilisi dolor Aenean. Ut' .
+ ' Aliquam {{volutpat}} arcu ultrices eu Ut quis [[:9001|9001]] et Donec.',
+ 'propertyCount' => 0,
+ 'propertyLabels' => [],
+ 'propertyValues' => []
+ ]
+ ];
+
+ // #5 NS_HELP enabled but no properties or links at all
+ $provider[] = [
+ NS_HELP,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_HELP => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' Suspendisse tincidunt semper facilisi dolor Aenean.',
+ [
+ 'resultText' => 'Lorem ipsum dolor sit &$% consectetuer auctor at quis' .
+ ' Suspendisse tincidunt semper facilisi dolor Aenean.',
+ 'propertyCount' => 0,
+ 'propertyLabels' => [],
+ 'propertyValues' => []
+ ]
+ ];
+
+ // #6 Bug 54967
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ '[[Foo::?bar]], [[Foo::Baz?]], [[Quxey::B?am]]',
+ [
+ 'resultText' => '[[:?bar|?bar]], [[:Baz?|Baz?]], [[:B?am|B?am]]',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Foo', 'Quxey' ],
+ 'propertyValues' => [ '?bar', 'Baz?', 'B?am' ]
+ ]
+ ];
+
+ #7 673
+
+ // Special:Types/Number
+ $specialTypeName = \SpecialPage::getTitleFor( 'Types', 'Number' )->getPrefixedText();
+
+ $provider[] = [
+ SMW_NS_PROPERTY,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ SMW_NS_PROPERTY => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ '[[has type::number]], [[has Type::page]] ',
+ [
+ 'resultText' => "[[$specialTypeName|number]], [[:Page|page]]",
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Has type', 'Has Type' ],
+ 'propertyValues' => [ 'Number', 'Page' ]
+ ]
+ ];
+
+ #8 1048, Double-double
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ '[[Foo::Bar::Foobar]], [[IPv6::fc00:123:8000::/64]] [[ABC::10.1002/::AID-MRM16::]]',
+ [
+ 'resultText' => '[[:Bar::Foobar|Bar::Foobar]], [[:Fc00:123:8000::/64|fc00:123:8000::/64]] [[:10.1002/::AID-MRM16::|10.1002/::AID-MRM16::]]',
+ 'propertyCount' => 3,
+ 'propertyLabels' => [ 'Foo', 'IPv6', 'ABC' ],
+ 'propertyValues' => [ 'Bar::Foobar', 'Fc00:123:8000::/64', '10.1002/::AID-MRM16::' ]
+ ]
+ ];
+
+ #9 T32603
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR,
+ ],
+ '[[Foo:::Foobar]] [[Bar:::ABC|DEF]] [[Foo:::0049 30 12345678/::Foo]] ',
+ [
+ 'resultText' => '[[:Foobar|Foobar]] [[:ABC|DEF]] [[:0049 30 12345678/::Foo|0049 30 12345678/::Foo]]',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Foo', 'Bar' ],
+ 'propertyValues' => [ 'Foobar', '0049 30 12345678/::Foo', 'ABC' ]
+ ]
+ ];
+
+ #10 #1252 (disabled strict mode)
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_NONE
+ ],
+ '[[Foo::Foobar::テスト]] [[Bar:::ABC|DEF]] [[Foo:::0049 30 12345678/::Foo]] ',
+ [
+ 'resultText' => '[[:テスト|テスト]] [[:ABC|DEF]] [[:Foo|Foo]]',
+ 'propertyCount' => 4,
+ 'propertyLabels' => [ 'Foo', 'Bar:', 'Foobar', ':0049 30 12345678/' ],
+ 'propertyValues' => [ 'Foobar', 'Foo', 'ABC', 'テスト' ]
+ ]
+ ];
+
+ #11 #1747 (left pipe)
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR | SMW_PARSER_NONE
+ ],
+ '[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[File:Example.png|Bar::Foobar|link=Foo]]',
+ [
+ 'resultText' => '[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[File:Example.png|Bar::Foobar|link=Foo]]',
+ 'propertyCount' => 0,
+ ]
+ ];
+
+ #12 #1747 (left pipe + including one annotation)
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR | SMW_PARSER_STRICT
+ ],
+ '[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[Foo::Foobar::テスト]] [[File:Example.png|Bar::Foobar|link=Foo]]',
+ [
+ 'resultText' => '[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[:Foobar::テスト|Foobar::テスト]] [[File:Example.png|Bar::Foobar|link=Foo]]',
+ 'propertyCount' => 1,
+ 'propertyLabels' => [ 'Foo' ],
+ 'propertyValues' => [ 'Foobar::テスト' ]
+ ]
+ ];
+
+ #13 @@@ syntax
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR | SMW_PARSER_STRICT
+ ],
+ '[[Foo::@@@]] [[Bar::@@@en|Foobar]]',
+ [
+ 'resultText' => $testEnvironment->replaceNamespaceWithLocalizedText( SMW_NS_PROPERTY, '[[:Property:Foo|Foo]] [[:Property:Bar|Foobar]]' ),
+ 'propertyCount' => 0
+ ]
+ ];
+
+ #14 [ ... ] in-text link
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR | SMW_PARSER_STRICT | SMW_PARSER_LINV
+ ],
+ '[[Text::Bar [http://example.org/Foo Foo]]] [[Code::Foo[1] Foobar]]',
+ [
+ 'resultText' => 'Bar [http://example.org/Foo Foo] <div class="smwpre">Foo&#91;1]&#160;Foobar</div>',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Text', 'Code' ],
+ 'propertyValues' => [ 'Bar [http://example.org/Foo Foo]', 'Foo[1] Foobar' ]
+ ]
+ ];
+
+ #15 (#2671) external [] decode use
+ $provider[] = [
+ NS_MAIN,
+ [
+ 'smwgNamespacesWithSemanticLinks' => [ NS_MAIN => true ],
+ 'smwgParserFeatures' => SMW_PARSER_INL_ERROR | SMW_PARSER_STRICT | SMW_PARSER_LINV
+ ],
+ '<sup id="cite_ref-1" class="reference">[[#cite_note-1|&#91;1&#93;]]</sup>',
+ [
+ 'resultText' => '<sup id="cite_ref-1" class="reference">[[#cite_note-1|&#91;1&#93;]]</sup>'
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function magicWordDataProvider() {
+
+ $provider = [];
+
+ // #0 __NOFACTBOX__
+ $provider[] = [
+ NS_MAIN,
+ 'Lorem ipsum dolor [[Foo::dictumst cursus]] facilisi __NOFACTBOX__',
+ [ 'SMW_NOFACTBOX' ]
+ ];
+
+ // #1 __SHOWFACTBOX__
+ $provider[] = [
+ NS_HELP,
+ 'Lorem ipsum dolor [[Foo::dictumst cursus]] facilisi __SHOWFACTBOX__',
+ [ 'SMW_SHOWFACTBOX' ]
+ ];
+
+ // #2 __NOFACTBOX__, __SHOWFACTBOX__
+ $provider[] = [
+ NS_HELP,
+ 'Lorem ipsum dolor [[Foo::dictumst cursus]] facilisi __NOFACTBOX__ __SHOWFACTBOX__',
+ [ 'SMW_NOFACTBOX', 'SMW_SHOWFACTBOX' ]
+ ];
+
+ // #3 __SHOWFACTBOX__, __NOFACTBOX__
+ $provider[] = [
+ NS_HELP,
+ 'Lorem ipsum dolor [[Foo::dictumst cursus]] facilisi __SHOWFACTBOX__ __NOFACTBOX__',
+ [ 'SMW_NOFACTBOX', 'SMW_SHOWFACTBOX' ]
+ ];
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksEncoderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksEncoderTest.php
new file mode 100644
index 00000000..685470f9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksEncoderTest.php
@@ -0,0 +1,156 @@
+<?php
+
+namespace SMW\Tests\Parser;
+
+use SMW\Parser\LinksEncoder;
+
+/**
+ * @covers \SMW\Parser\LinksEncoder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class LinksEncoderTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider obfuscateProvider
+ */
+ public function testRoundTripLinkObfuscation( $text ) {
+
+ $newText = LinksEncoder::encodeLinks( $text );
+
+ $this->assertEquals(
+ $text,
+ LinksEncoder::removeLinkObfuscation( $newText )
+ );
+ }
+
+ /**
+ * @dataProvider obfuscateProvider
+ */
+ public function testfindAndEncodeLinks( $text, $expected ) {
+
+ $inTextAnnotationParser = $this->getMockBuilder( 'SMW\Parser\InTextAnnotationParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertEquals(
+ $expected,
+ LinksEncoder::findAndEncodeLinks( $text, $inTextAnnotationParser )
+ );
+ }
+
+ /**
+ * @dataProvider stripTextWithAnnotationProvider
+ */
+ public function testStrip( $text, $expectedRemoval, $expectedObscuration ) {
+
+ $this->assertEquals(
+ $expectedRemoval,
+ LinksEncoder::removeAnnotation( $text )
+ );
+
+ $this->assertEquals(
+ $expectedObscuration,
+ LinksEncoder::obfuscateAnnotation( $text )
+ );
+ }
+
+ public function stripTextWithAnnotationProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ 'Suspendisse [[Bar::tincidunt semper|abc]] facilisi',
+ 'Suspendisse abc facilisi',
+ 'Suspendisse &#91;&#91;Bar::tincidunt semper|abc]] facilisi'
+ ];
+
+ $provider[] = [
+ 'Suspendisse [[Bar::tincidunt semper]] facilisi',
+ 'Suspendisse tincidunt semper facilisi',
+ 'Suspendisse &#91;&#91;Bar::tincidunt semper]] facilisi'
+ ];
+
+ $provider[] = [
+ 'Suspendisse [[:Tincidunt semper|tincidunt semper]]',
+ 'Suspendisse [[:Tincidunt semper|tincidunt semper]]',
+ 'Suspendisse [[:Tincidunt semper|tincidunt semper]]'
+ ];
+
+ $provider[] = [
+ '[[Foo::Foobar::テスト]] [[Bar:::ABC|DEF]] [[Foo:::0049 30 12345678/::Foo]]',
+ 'Foobar::テスト DEF :0049 30 12345678/::Foo',
+ '&#91;&#91;Foo::Foobar::テスト]] &#91;&#91;Bar:::ABC|DEF]] &#91;&#91;Foo:::0049 30 12345678/::Foo]]'
+ ];
+
+ $provider[] = [
+ '%5B%5BFoo%20Bar::foobaz%5D%5D',
+ 'foobaz',
+ '&#91;&#91;Foo%20Bar::foobaz]]'
+ ];
+
+ $provider[] = [
+ 'Suspendisse tincidunt semper facilisi',
+ 'Suspendisse tincidunt semper facilisi',
+ 'Suspendisse tincidunt semper facilisi'
+ ];
+
+ // #1747
+ $provider[] = [
+ '[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[File:Example.png|Bar::Foobar|link=Foo]]',
+ '[[Foo|Bar::Foobar]] [[File:Example.png|alt=Bar::Foobar|Caption]] [[File:Example.png|Bar::Foobar|link=Foo]]',
+ '&#91;&#91;Foo|Bar::Foobar]] &#91;&#91;File:Example.png|alt=Bar::Foobar|Caption]] &#91;&#91;File:Example.png|Bar::Foobar|link=Foo]]'
+ ];
+
+ $provider[] = [
+ '[[Foo::@@@]] [[Bar::@@@|123]]',
+ ' 123',
+ '&#91;&#91;Foo::@@@]] &#91;&#91;Bar::@@@|123]]'
+ ];
+
+ $provider[] = [
+ 'Suspendisse [[SMW::off]][[Bar::tincidunt semper|abc]] facilisi[[SMW::on]] [[Bar:::ABC|DEF]]',
+ 'Suspendisse abc facilisi DEF',
+ 'Suspendisse &#91;&#91;SMW::off]]&#91;&#91;Bar::tincidunt semper|abc]] facilisi&#91;&#91;SMW::on]] &#91;&#91;Bar:::ABC|DEF]]'
+ ];
+
+ return $provider;
+ }
+
+ public function obfuscateProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ 'Foo',
+ 'Foo'
+ ];
+
+ $provider[] = [
+ '[[Foo]]',
+ '[[Foo]]'
+ ];
+
+ $provider[] = [
+ '[[Foo|Bar]]',
+ '[[Foo|Bar]]'
+ ];
+
+ $provider[] = [
+ '[[Foo::[[Bar]]]]',
+ '[[Foo::&#x005B;&#x005B;Bar&#x005D;&#x005D;]]'
+ ];
+
+ $provider[] = [
+ '[[Foo::[[Foo|Bar]]]]',
+ '[[Foo::&#x005B;&#x005B;Foo&#124;Bar&#x005D;&#x005D;]]'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksProcessorTest.php
new file mode 100644
index 00000000..f855bf18
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/LinksProcessorTest.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace SMW\Tests\Parser;
+
+use SMW\Parser\LinksProcessor;
+
+/**
+ * @covers \SMW\Parser\LinksProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class LinksProcessorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new LinksProcessor();
+
+ $this->assertInstanceOf(
+ 'SMW\Parser\LinksProcessor',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider semanticPreLinkProvider
+ */
+ public function testPreprocess( $semanticLink, $expected ) {
+
+ $instance = new LinksProcessor();
+
+ $this->assertEquals(
+ $expected,
+ $instance->preprocess( $semanticLink )
+ );
+ }
+
+ /**
+ * @dataProvider semanticLinkProvider
+ */
+ public function testProcess( $semanticLink, $expected ) {
+
+ $instance = new LinksProcessor();
+
+ $this->assertEquals(
+ $expected,
+ $instance->process( $semanticLink )
+ );
+ }
+
+ public function semanticPreLinkProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ [
+ '[[Foo::Bar]]',
+ 'Foo',
+ 'Bar'
+ ],
+ [
+ '[[Foo::Bar]]',
+ 'Foo',
+ 'Bar'
+ ]
+ ];
+
+ $provider[] = [
+ [
+ '[[Foo::Bar|Foobar]]',
+ 'Foo',
+ 'Bar'
+ ],
+ [
+ '[[Foo::Bar|Foobar]]',
+ 'Foo',
+ 'Bar'
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function semanticLinkProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ [
+ '[[Foo::Bar]]',
+ 'Foo',
+ 'Bar'
+ ],
+ [
+ [
+ 'Foo'
+ ],
+ 'Bar',
+ false
+ ]
+ ];
+
+ $provider[] = [
+ [
+ '[[Foo::Bar|Foobar]]',
+ 'Foo',
+ 'Bar'
+ ],
+ [
+ [
+ 'Foo'
+ ],
+ 'Bar',
+ false
+ ]
+ ];
+
+ $provider[] = [
+ [
+ '[[Foo::=Bar|Foobar]]',
+ 'Foo',
+ '=Bar'
+ ],
+ [
+ [
+ 'Foo'
+ ],
+ '=Bar',
+ false
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/RecursiveTextProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/RecursiveTextProcessorTest.php
new file mode 100644
index 00000000..5ad38dec
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/RecursiveTextProcessorTest.php
@@ -0,0 +1,345 @@
+<?php
+
+namespace SMW\Tests\Parser;
+
+use SMW\Parser\RecursiveTextProcessor;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Parser\RecursiveTextProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RecursiveTextProcessorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $parser;
+ private $parserOptions;
+ private $parserOutput;
+ private $title;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->parserOutput->expects( $this->any() )
+ ->method( 'getHeadItems' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ RecursiveTextProcessor::class,
+ new RecursiveTextProcessor( $this->parser )
+ );
+ }
+
+ public function testRecursivePreprocess_NO_RecursiveAnnotation() {
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $this->parserOptions ) );
+
+ $this->parser->expects( $this->once() )
+ ->method( 'replaceVariables' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $this->assertSame(
+ '[[SMW::off]]Foo[[SMW::on]]',
+ $instance->recursivePreprocess( 'Foo' )
+ );
+ }
+
+ public function testRecursivePreprocess_NO_RecursiveAnnotationWithAnnotationBlockToRemoveCategories() {
+
+ $this->parserOutput->expects( $this->atLeastOnce() )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( \SMW\ParserData::ANNOTATION_BLOCK ) )
+ ->will( $this->returnValue( [ '123' => true ] ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->parserOutput ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $this->parserOptions ) );
+
+ $this->parser->expects( $this->once() )
+ ->method( 'replaceVariables' )
+ ->with( $this->equalTo( 'Foo [[Category:Bar]][[Category:Test: Abc]]' ) )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->uniqid( '123' );
+
+ $this->assertSame(
+ '[[SMW::off]]Foo [[SMW::on]]',
+ $instance->recursivePreprocess( 'Foo [[Category:Bar]][[Category:Test: Abc]]' )
+ );
+ }
+
+ public function testRecursivePreprocess_NO_RecursiveAnnotationWithNoAnnotationBlockToRetainCategories() {
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->parserOutput ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $this->parserOptions ) );
+
+ $this->parser->expects( $this->once() )
+ ->method( 'replaceVariables' )
+ ->with( $this->equalTo( 'Foo [[Category:Bar]][[Category:Test: Abc]]' ) )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->uniqid( '123' );
+
+ $this->assertSame(
+ '[[SMW::off]]Foo [[Category:Bar]][[Category:Test: Abc]][[SMW::on]]',
+ $instance->recursivePreprocess( 'Foo [[Category:Bar]][[Category:Test: Abc]]' )
+ );
+ }
+
+ public function testRecursivePreprocess_WITH_RecursiveAnnotation() {
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $this->parserOptions ) );
+
+ $this->parser->expects( $this->once() )
+ ->method( 'recursivePreprocess' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->setRecursiveAnnotation( true );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->recursivePreprocess( 'Foo' )
+ );
+ }
+
+ public function testRecursivePreprocess_WITH_IncompleteParser() {
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->setRecursiveAnnotation( false );
+
+ $this->assertSame(
+ '[[SMW::off]]Foo[[SMW::on]]',
+ $instance->recursivePreprocess( 'Foo' )
+ );
+
+ $instance->setRecursiveAnnotation( true );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->recursivePreprocess( 'Foo' )
+ );
+ }
+
+ public function testRecursiveTagParse() {
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $this->parserOptions ) );
+
+ $this->parser->expects( $this->once() )
+ ->method( 'recursiveTagParse' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->recursiveTagParse( 'Foo' )
+ );
+ }
+
+ public function testRecursiveTagParse_WITH_IncompleteParser() {
+
+ $this->parser->expects( $this->once() )
+ ->method( 'parse' )
+ ->with( $this->equalTo( 'Foo__NOTOC__' ) )
+ ->will( $this->returnValue( $this->parserOutput ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->recursiveTagParse( 'Foo' );
+ }
+
+ public function testExpandTemplates() {
+
+ $this->parser->expects( $this->once() )
+ ->method( 'preprocess' )
+ ->with( $this->equalTo( '{{Foo}}' ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->expandTemplates( '{{Foo}}' );
+ }
+
+ public function testRecursivePreprocess_ExceededRecursion() {
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->title ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( $this->parserOptions ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->setMaxRecursionDepth( 0 );
+ $instance->recursivePreprocess( 'Foo' );
+
+ $this->assertNotEmpty(
+ $instance->getError()
+ );
+ }
+
+ public function testRecursiveTagParse_ExceededRecursion() {
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->setMaxRecursionDepth( 0 );
+ $instance->recursiveTagParse( 'Foo' );
+
+ $this->assertNotEmpty(
+ $instance->getError()
+ );
+ }
+
+ public function testTranscludeAnnotationWithoutUniquidThrowsException() {
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->parserOutput ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->transcludeAnnotation( false );
+ }
+
+ public function testTranscludeAnnotation_FALSE() {
+
+ $this->parserOutput->expects( $this->atLeastOnce() )
+ ->method( 'setExtensionData' )
+ ->with(
+ $this->equalTo( \SMW\ParserData::ANNOTATION_BLOCK ),
+ $this->equalTo( [ '123' => true ] ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->parserOutput ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->uniqid( '123' );
+ $instance->transcludeAnnotation( false );
+ }
+
+ public function testReleaseAnnotationBlock() {
+
+ $this->parserOutput->expects( $this->atLeastOnce() )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( \SMW\ParserData::ANNOTATION_BLOCK ) )
+ ->will( $this->returnValue( [ '123' => true ] ) );
+
+ $this->parserOutput->expects( $this->atLeastOnce() )
+ ->method( 'setExtensionData' )
+ ->with(
+ $this->equalTo( \SMW\ParserData::ANNOTATION_BLOCK ),
+ $this->equalTo( false ) );
+
+ $this->parser->expects( $this->atLeastOnce() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->parserOutput ) );
+
+ $instance = new RecursiveTextProcessor(
+ $this->parser
+ );
+
+ $instance->uniqid( '123' );
+ $instance->releaseAnnotationBlock();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/SemanticLinksParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/SemanticLinksParserTest.php
new file mode 100644
index 00000000..96956f0d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Parser/SemanticLinksParserTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\Parser;
+
+use SMW\Parser\LinksProcessor;
+use SMW\Parser\SemanticLinksParser;
+
+/**
+ * @covers \SMW\Parser\SemanticLinksParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SemanticLinksParserTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $linksProcessor = $this->getMockBuilder( 'SMW\Parser\LinksProcessor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SemanticLinksParser( $linksProcessor );
+
+ $this->assertInstanceOf(
+ 'SMW\Parser\SemanticLinksParser',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider textProvider
+ */
+ public function testParse( $text, $expected ) {
+
+ $instance = new SemanticLinksParser(
+ new LinksProcessor()
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->parse( $text )
+ );
+ }
+
+ public function textProvider() {
+
+ $provider = [];
+
+ $provider[] = [
+ 'Foo',
+ []
+ ];
+
+ $provider[] = [
+ '[[Foo]]',
+ []
+ ];
+
+ $provider[] = [
+ '[[Foo|Bar]]',
+ []
+ ];
+
+ $provider[] = [
+ '[[Foo::[[Bar]]]]',
+ []
+ ];
+
+ $provider[] = [
+ '[[Foo::Bar]]',
+ [
+ [
+ 'Foo'
+ ],
+ 'Bar',
+ false
+ ]
+ ];
+
+ $provider[] = [
+ '[[Foo::Bar|Foobar]]',
+ [
+ [
+ 'Foo'
+ ],
+ 'Bar',
+ 'Foobar'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserDataTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserDataTest.php
new file mode 100644
index 00000000..c18784bf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserDataTest.php
@@ -0,0 +1,488 @@
+<?php
+
+namespace SMW\Tests;
+
+use ParserOutput;
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\ParserData;
+use SMW\SemanticData;
+use Title;
+
+/**
+ * @covers \SMW\ParserData
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParserDataTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $dataValueFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( -1 ) );
+
+ $parserOutput = $this->getMockBuilder( 'ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserData',
+ new ParserData( $title, $parserOutput )
+ );
+ }
+
+ public function testInitialDataIsEmpty() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData( $title, $parserOutput );
+
+ $this->assertTrue(
+ $instance->getSemanticData()->isEmpty()
+ );
+ }
+
+ public function testUpdateJobState() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData( $title, $parserOutput );
+
+ $instance->setOption( ParserData::OPT_CREATE_UPDATE_JOB, false );
+
+ $this->assertFalse(
+ $instance->getOption( ParserData::OPT_CREATE_UPDATE_JOB )
+ );
+ }
+
+ public function testGetterInstances() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData( $title, $parserOutput );
+
+ $this->assertInstanceOf(
+ 'Title',
+ $instance->getTitle()
+ );
+
+ $this->assertInstanceOf(
+ 'ParserOutput',
+ $instance->getOutput()
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $instance->getSubject()
+ );
+ }
+
+ public function testAddDataVlaueAndClear() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData( $title, $parserOutput );
+
+ $this->assertTrue(
+ $instance->getSemanticData()->isEmpty()
+ );
+
+ $instance->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $this->assertFalse(
+ $instance->getSemanticData()->isEmpty()
+ );
+
+ $instance->setEmptySemanticData();
+
+ $this->assertTrue(
+ $instance->getSemanticData()->isEmpty()
+ );
+ }
+
+ public function testAddDataValueAndPushSemanticDataToParserOutput() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData( $title, $parserOutput );
+
+ $instance->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $this->assertFalse( $instance->getSemanticData()->isEmpty() );
+ $instance->pushSemanticDataToParserOutput();
+
+ $title = Title::newFromText( __METHOD__ .'-1' );
+
+ $newInstance = new ParserData( $title, $instance->getOutput() );
+
+ $this->assertEquals(
+ $instance->getSemanticData()->getHash(),
+ $newInstance->getSemanticData()->getHash()
+ );
+ }
+
+ public function testSetGetSemanticData() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData( $title, $parserOutput );
+
+ $this->assertTrue( $instance->getSemanticData()->isEmpty() );
+
+ $semanticData = new SemanticData(
+ DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) )
+ );
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $instance->setSemanticData( $semanticData );
+
+ $this->assertFalse( $instance->getSemanticData()->isEmpty() );
+
+ $this->assertEquals(
+ $semanticData->getHash(),
+ $instance->getSemanticData()->getHash()
+ );
+ }
+
+ public function getPropertyValueDataProvider() {
+ return [
+ [ 'Foo' , 'Bar', 0, 1 ],
+ [ '-Foo' , 'Bar', 1, 0 ],
+ [ '_Foo' , 'Bar', 1, 0 ],
+ ];
+ }
+
+ /**
+ * @dataProvider getPropertyValueDataProvider
+ */
+ public function testAddDataValue( $propertyName, $value, $errorCount, $propertyCount ) {
+
+ $title = Title::newFromText( __METHOD__ );
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData( $title, $parserOutput );
+
+ $instance->addDataValue(
+ $this->dataValueFactory->newDataValueByText(
+ $propertyName,
+ $value
+ )
+ );
+
+ if ( $errorCount > 0 ) {
+ return $this->assertCount( $errorCount, $instance->getSemanticData()->getErrors() );
+ }
+
+ $expected = [
+ 'propertyCount' => $propertyCount,
+ 'propertyLabels' => $propertyName,
+ 'propertyValues' => $value
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testUpdateStore() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'clearData', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'clearData' );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $this->assertTrue(
+ $instance->updateStore()
+ );
+ }
+
+ public function testSkipUpdateOnMatchedMarker() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $logger = $this->getMockBuilder( '\Psr\Log\LoggerInterface' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->with( $this->stringContains( ':smw:update:7fe0bc8114c23c928b25316e4858fceb' ) )
+ ->will( $this->returnValue( 42 ) );
+
+ $cache->expects( $this->once() )
+ ->method( 'save' )
+ ->with( $this->stringContains( ':smw:update:7fe0bc8114c23c928b25316e4858fceb' ) );
+
+ $instance = new ParserData(
+ $title,
+ new ParserOutput(),
+ $cache
+ );
+
+ $instance->setLogger( $logger );
+ $instance->markUpdate( 42 );
+
+ $this->assertFalse(
+ $instance->updateStore()
+ );
+ }
+
+ public function testHasSemanticData() {
+
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ $parserOutput
+ );
+
+ $this->assertFalse(
+ $instance->hasSemanticData( $parserOutput )
+ );
+
+ $instance->addDataValue(
+ $this->dataValueFactory->newDataValueByText(
+ 'Foo',
+ 'Bar'
+ )
+ );
+
+ $instance->markParserOutput();
+
+ $this->assertTrue(
+ $instance->hasSemanticData( $parserOutput )
+ );
+ }
+
+ public function testImportFromParserOutput() {
+
+ $import = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $import->addDataValue(
+ $this->dataValueFactory->newDataValueByText(
+ 'Foo',
+ 'Bar'
+ )
+ );
+
+ $import->pushSemanticDataToParserOutput();
+
+ $instance = new ParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance->importFromParserOutput( null );
+
+ $this->assertNotEquals(
+ $import->getSemanticData()->getHash(),
+ $instance->getSemanticData()->getHash()
+ );
+
+ $instance->importFromParserOutput( $import->getOutput() );
+
+ $this->assertEquals(
+ $import->getSemanticData()->getHash(),
+ $instance->getSemanticData()->getHash()
+ );
+ }
+
+ public function testAddLimitReport() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( -1 ) );
+
+ $parserOutput = $this->getMockBuilder( 'ParserOutput' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'setLimitReportData' ] )
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'setLimitReportData' )
+ ->with(
+ $this->stringContains( 'smw-limitreport-Foo' ),
+ $this->stringContains( 'Bar' ) );
+
+ // FIXME 1.22+
+ if ( !method_exists( $parserOutput, 'setLimitReportData' ) ) {
+ $this->markTestSkipped( 'LimitReportData is not available.' );
+ }
+
+ $instance = new ParserData( $title, $parserOutput );
+ $instance->addLimitReport( 'Foo', 'Bar' );
+ }
+
+ public function testIsBlocked() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( -1 ) );
+
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData(
+ $title,
+ $parserOutput
+ );
+
+ $this->assertFalse(
+ $instance->isBlocked()
+ );
+
+ $parserOutput->setExtensionData( ParserData::ANNOTATION_BLOCK, true );
+
+ $this->assertTrue(
+ $instance->isBlocked()
+ );
+ }
+
+ public function testSetGetOption() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( -1 ) );
+
+ $parserOutput = new ParserOutput();
+
+ $instance = new ParserData(
+ $title,
+ $parserOutput
+ );
+
+ $instance->setOption( $instance::NO_QUERY_DEPENDENCY_TRACE, true );
+
+ $this->assertTrue(
+ $instance->getOption( $instance::NO_QUERY_DEPENDENCY_TRACE )
+ );
+ }
+
+ public function testAddExtraParserKey() {
+
+ $parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOptions->expects( $this->once() )
+ ->method( 'addExtraKey' )
+ ->with( $this->stringContains( 'Foo' ) );
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( -1 ) );
+
+ $parserOutput = $this->getMockBuilder( 'ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'recordOption' )
+ ->with( $this->stringContains( 'userlang' ) );
+
+ $instance = new ParserData(
+ $title,
+ $parserOutput
+ );
+
+ $instance->setParserOptions( $parserOptions );
+ $instance->addExtraParserKey( 'Foo' );
+ $instance->addExtraParserKey( 'userlang' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctionFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctionFactoryTest.php
new file mode 100644
index 00000000..c89b2dee
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctionFactoryTest.php
@@ -0,0 +1,210 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ParserFunctionFactory;
+
+/**
+ * @covers \SMW\ParserFunctionFactory
+ * @group smenatic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParserFunctionFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $parserFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'ParserData', $this->parserData );
+
+ $this->parserFactory = $this->testEnvironment->getUtilityFactory()->newParserFactory();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctionFactory',
+ new ParserFunctionFactory( $parser )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctionFactory',
+ ParserFunctionFactory::newFromParser( $parser )
+ );
+ }
+
+ /**
+ * @dataProvider parserFunctionProvider
+ */
+ public function testParserFunctionInstance( $instance, $method ) {
+
+ $parser = $this->parserFactory->create( __METHOD__ );
+
+ $parserFunctionFactory = new ParserFunctionFactory( $parser );
+
+ $this->assertInstanceOf(
+ $instance,
+ call_user_func_array( [ $parserFunctionFactory, $method ], [ $parser ] )
+ );
+ }
+
+ /**
+ * @dataProvider parserFunctionDefinitionProvider
+ */
+ public function testParserFunctionDefinition( $method, $expected ) {
+
+ $parser = $this->parserFactory->create( __METHOD__ );
+
+ $parserFunctionFactory = new ParserFunctionFactory( $parser );
+
+ $definition = call_user_func_array(
+ [ $parserFunctionFactory, $method ],
+ [ '' ]
+ );
+
+ $this->assertEquals(
+ $expected,
+ $definition[0]
+ );
+
+ $this->assertInstanceOf(
+ '\Closure',
+ $definition[1]
+ );
+
+ $this->assertInternalType(
+ 'integer',
+ $definition[2]
+ );
+ }
+
+ public function testAskParserFunctionWithParserOption() {
+
+ $this->parserData->expects( $this->at( 0 ) )
+ ->method( 'setOption' )
+ ->with(
+ $this->equalTo( \SMW\ParserData::NO_QUERY_DEPENDENCY_TRACE ),
+ $this->anything() );
+
+ $parser = $this->parserFactory->create( __METHOD__ );
+ $parser->getOptions()->smwAskNoDependencyTracking = true;
+
+ $parserFunctionFactory = new ParserFunctionFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\AskParserFunction',
+ $parserFunctionFactory->newAskParserFunction( $parser )
+ );
+ }
+
+ public function parserFunctionProvider() {
+
+ $provider[] = [
+ '\SMW\ParserFunctions\RecurringEventsParserFunction',
+ 'getRecurringEventsParser'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\SubobjectParserFunction',
+ 'getSubobjectParser'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\RecurringEventsParserFunction',
+ 'newRecurringEventsParserFunction'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\SubobjectParserFunction',
+ 'newSubobjectParserFunction'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\AskParserFunction',
+ 'newAskParserFunction'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\ShowParserFunction',
+ 'newShowParserFunction'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\SetParserFunction',
+ 'newSetParserFunction'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\ConceptParserFunction',
+ 'newConceptParserFunction'
+ ];
+
+ $provider[] = [
+ '\SMW\ParserFunctions\DeclareParserFunction',
+ 'newDeclareParserFunction'
+ ];
+
+ return $provider;
+ }
+
+ public function parserFunctionDefinitionProvider() {
+
+ $provider[] = [
+ 'getAskParserFunctionDefinition',
+ 'ask'
+ ];
+
+ $provider[] = [
+ 'getShowParserFunctionDefinition',
+ 'show'
+ ];
+
+ $provider[] = [
+ 'getSubobjectParserFunctionDefinition',
+ 'subobject'
+ ];
+
+ $provider[] = [
+ 'getSetRecurringEventParserFunctionDefinition',
+ 'set_recurring_event'
+ ];
+
+ $provider[] = [
+ 'getSetParserFunctionDefinition',
+ 'set'
+ ];
+
+ $provider[] = [
+ 'getConceptParserFunctionDefinition',
+ 'concept'
+ ];
+
+ $provider[] = [
+ 'getDeclareParserFunctionDefinition',
+ 'declare'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/AskParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/AskParserFunctionTest.php
new file mode 100644
index 00000000..e707eaef
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/AskParserFunctionTest.php
@@ -0,0 +1,585 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use ReflectionClass;
+use SMW\ApplicationFactory;
+use SMW\Localizer;
+use SMW\ParserFunctions\AskParserFunction;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\AskParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class AskParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $semanticDataValidator;
+ private $messageFormatter;
+ private $circularReferenceGuard;
+ private $expensiveFuncExecutionWatcher;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+
+ $this->testEnvironment->addConfiguration( 'smwgQueryProfiler', true );
+ $this->testEnvironment->addConfiguration( 'smwgQMaxLimit', 1000 );
+
+ $this->messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->expensiveFuncExecutionWatcher = $this->getMockBuilder( '\SMW\ParserFunctions\ExpensiveFuncExecutionWatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->expensiveFuncExecutionWatcher->expects( $this->any() )
+ ->method( 'hasReachedExpensiveLimit' )
+ ->will( $this->returnValue( false ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\AskParserFunction',
+ new AskParserFunction( $parserData, $this->messageFormatter, $this->circularReferenceGuard, $this->expensiveFuncExecutionWatcher )
+ );
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testParse( array $params ) {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->parse( $params )
+ );
+ }
+
+ public function testIsQueryDisabled() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->messageFormatter->expects( $this->any() )
+ ->method( 'addFromKey' )
+ ->will( $this->returnSelf() );
+
+ $this->messageFormatter->expects( $this->once() )
+ ->method( 'getHtml' );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $instance->isQueryDisabled();
+ }
+
+ public function testHasReachedExpensiveLimit() {
+
+ $params = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list'
+ ];
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $expensiveFuncExecutionWatcher = $this->getMockBuilder( '\SMW\ParserFunctions\ExpensiveFuncExecutionWatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $expensiveFuncExecutionWatcher->expects( $this->any() )
+ ->method( 'hasReachedExpensiveLimit' )
+ ->will( $this->returnValue( true ) );
+
+ $this->messageFormatter->expects( $this->any() )
+ ->method( 'addFromKey' )
+ ->will( $this->returnSelf() );
+
+ $this->messageFormatter->expects( $this->once() )
+ ->method( 'getHtml' );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $expensiveFuncExecutionWatcher
+ );
+
+ $instance->parse( $params );
+ }
+
+ public function testSetShowMode() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $reflector = new ReflectionClass( '\SMW\ParserFunctions\AskParserFunction' );
+ $showMode = $reflector->getProperty( 'showMode' );
+ $showMode->setAccessible( true );
+
+ $this->assertFalse( $showMode->getValue( $instance ) );
+ $instance->setShowMode( true );
+
+ $this->assertTrue( $showMode->getValue( $instance ) );
+ }
+
+ public function testCircularGuard() {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $this->circularReferenceGuard->expects( $this->once() )
+ ->method( 'mark' );
+
+ $this->circularReferenceGuard->expects( $this->never() )
+ ->method( 'unmark' );
+
+ $this->circularReferenceGuard->expects( $this->once() )
+ ->method( 'isCircular' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $params = [];
+
+ $this->assertEmpty(
+ $instance->parse( $params )
+ );
+ }
+
+ public function testQueryIdStabilityForFixedSetOfParametersWithFingerprintMethod() {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $params = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list'
+ ];
+
+ $instance->parse( $params );
+
+ $this->assertTrue(
+ $parserData->getSemanticData()->hasSubSemanticData( '_QUERYaa38249db4bc6d3e8133588fb08d0f0d' )
+ );
+
+ // Limit is a factor that influences the query id, count uses the
+ // max limit available in $GLOBALS['smwgQMaxLimit'] therefore we set
+ // the limit to make the test independent from possible other settings
+
+ $params = [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=count'
+ ];
+
+ $instance->parse( $params );
+
+ $this->assertTrue(
+ $parserData->getSemanticData()->hasSubSemanticData( '_QUERYb6a190747f7d3c2775730f6bc6c5e469' )
+ );
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testInstantiatedQueryData( array $params, array $expected, array $settings ) {
+
+ foreach ( $settings as $key => $value ) {
+ $this->testEnvironment->addConfiguration( $key, $value );
+ }
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $instance->parse( $params );
+
+ foreach ( $parserData->getSemanticData()->getSubSemanticData() as $containerSemanticData ){
+ $this->assertInstanceOf( 'SMWContainerSemanticData', $containerSemanticData );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $containerSemanticData
+ );
+ }
+ }
+
+ public function testEmbeddedQueryWithError() {
+
+ $params = [
+ '[[--ABC·|DEF::123]]',
+ 'format=table'
+ ];
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_ASK', '_ERRC' ],
+ ];
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $instance->parse( $params );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testWithDisabledQueryProfiler() {
+
+ $params = [
+ '[[Modification date::+]]',
+ 'format=table'
+ ];
+
+ $expected = [
+ 'propertyCount' => 0
+ ];
+
+ $this->testEnvironment->addConfiguration( 'smwgQueryProfiler', false );
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $instance->parse( $params );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testNoQueryProfileOnSpecialPages() {
+
+ $params = [
+ '[[Modification date::+]]',
+ 'format=table'
+ ];
+
+ $expected = [
+ 'propertyCount' => 0
+ ];
+
+ $this->testEnvironment->addConfiguration( 'smwgQueryProfiler', true );
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__, NS_SPECIAL ),
+ new ParserOutput()
+ );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $instance->parse( $params );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testQueryWithAnnotationMarker() {
+
+ $params = [
+ '[[Modification date::+]]',
+ 'format=table',
+ '@annotation'
+ ];
+
+ $postProcHandler = $this->getMockBuilder( '\SMW\PostProcHandler' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $postProcHandler->expects( $this->once() )
+ ->method( 'addUpdate' );
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $instance->setPostProcHandler( $postProcHandler );
+ $instance->parse( $params );
+ }
+
+ public function queryDataProvider() {
+
+ $categoryNS = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+ $fileNS = Localizer::getInstance()->getNamespaceTextById( NS_FILE );
+
+ $provider = [];
+
+ // #0
+ // {{#ask: [[Modification date::+]]
+ // |?Modification date
+ // |format=list
+ // }}
+ $provider[] = [
+ [
+ '[[Modification date::+]]',
+ '?Modification date',
+ 'format=list'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'list', 1, 1, '[[Modification date::+]]' ]
+ ],
+ [
+ 'smwgQueryProfiler' => true
+ ]
+ ];
+
+ // #1 Query string with spaces
+ // {{#ask: [[Modification date::+]] [[Category:Foo bar]] [[Has title::!Foo bar]]
+ // |?Modification date
+ // |?Has title
+ // |format=list
+ // }}
+ $provider[] = [
+ [
+ '[[Modification date::+]] [[Category:Foo bar]] [[Has title::!Foo bar]]',
+ '?Modification date',
+ '?Has title',
+ 'format=list'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'list', 4, 1, "[[Modification date::+]] [[$categoryNS:Foo bar]] [[Has title::!Foo bar]]" ]
+ ],
+ [
+ 'smwgCreateProtectionRight' => false,
+ 'smwgQueryProfiler' => true
+ ]
+ ];
+
+ // #2
+ // {{#ask: [[Modification date::+]][[Category:Foo]]
+ // |?Modification date
+ // |?Has title
+ // |format=list
+ // }}
+ $provider[] = [
+ [
+ '[[Modification date::+]][[Category:Foo]]',
+ '?Modification date',
+ '?Has title',
+ 'format=list'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'list', 2, 1, "[[Modification date::+]] [[$categoryNS:Foo]]" ]
+ ],
+ [
+ 'smwgQueryProfiler' => true
+ ]
+ ];
+
+ // #3 Known format
+ // {{#ask: [[File:Fooo]]
+ // |?Modification date
+ // |default=no results
+ // |format=feed
+ // }}
+ $provider[] = [
+ [
+ '[[File:Fooo]]',
+ '?Modification date',
+ 'default=no results',
+ 'format=feed'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'feed', 1, 1, "[[:$fileNS:Fooo]]" ]
+ ],
+ [
+ 'smwgQueryProfiler' => true
+ ]
+ ];
+
+ // #4 Unknown format, default table
+ // {{#ask: [[Modification date::+]][[Category:Foo]]
+ // |?Modification date
+ // |?Has title
+ // |format=bar
+ // }}
+ $provider[] = [
+ [
+ '[[Modification date::+]][[Category:Foo]]',
+ '?Modification date',
+ '?Has title',
+ 'format=lula'
+ ],
+ [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO' ],
+ 'propertyValues' => [ 'table', 2, 1, "[[Modification date::+]] [[$categoryNS:Foo]]" ]
+ ],
+ [
+ 'smwgQueryProfiler' => true
+ ]
+ ];
+
+ // #6 Invalid parameters
+ // {{#ask: [[Modification date::+]]
+ // |?Modification date
+ // |format=list
+ // |someParameterWithoutValue
+ // |{{{template}}}
+ // |@internal
+ // }}
+ $provider[] = [
+ [
+ '[[Modification date::+]]',
+ 'someParameterWithoutValue',
+ '{{{template}}}',
+ 'format=list',
+ '@internal',
+ '?Modification date'
+ ],
+ [
+ 'propertyCount' => 5,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE', '_ASKFO', '_ASKPA' ],
+ 'propertyValues' => [ 'list', 1, 1, '[[Modification date::+]]', '{"limit":50,"offset":0,"sort":[""],"order":["asc"],"mode":1}' ]
+ ],
+ [
+ 'smwgQueryProfiler' => SMW_QPRFL_PARAMS
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ConceptParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ConceptParserFunctionTest.php
new file mode 100644
index 00000000..63e9c31d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ConceptParserFunctionTest.php
@@ -0,0 +1,247 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use SMW\ApplicationFactory;
+use SMW\ParserFunctions\ConceptParserFunction;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\ConceptParserFunction
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ConceptParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\ConceptParserFunction',
+ new ConceptParserFunction( $parserData, $messageFormatter )
+ );
+ }
+
+ /**
+ * @dataProvider namespaceDataProvider
+ */
+ public function testErrorForNonConceptNamespace( $namespace ) {
+
+ $parserData = $this->applicationFactory->newParserData(
+ Title::newFromText( __METHOD__, $namespace ),
+ new ParserOutput()
+ );
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter->expects( $this->once() )
+ ->method( 'addFromKey' )
+ ->with( $this->equalTo( 'smw_no_concept_namespace' ) )
+ ->will( $this->returnSelf() );
+
+ $instance = new ConceptParserFunction( $parserData, $messageFormatter );
+ $instance->parse( [] );
+ }
+
+ /**
+ * @dataProvider queryParameterProvider
+ */
+ public function testErrorForOnDoubleParse( array $params ) {
+
+ $parserData = $this->applicationFactory->newParserData(
+ Title::newFromText( __METHOD__, SMW_NS_CONCEPT ),
+ new ParserOutput()
+ );
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter->expects( $this->any() )
+ ->method( 'addFromArray' )
+ ->will( $this->returnSelf() );
+
+ $messageFormatter->expects( $this->once() )
+ ->method( 'addFromKey' )
+ ->with( $this->equalTo( 'smw_multiple_concepts' ) )
+ ->will( $this->returnSelf() );
+
+ $instance = new ConceptParserFunction( $parserData, $messageFormatter );
+
+ $instance->parse( $params );
+ $instance->parse( $params );
+ }
+
+ public function testExistForFoundMessageFormatterEntry() {
+
+ $parserData = $this->applicationFactory->newParserData(
+ Title::newFromText( __METHOD__, SMW_NS_CONCEPT ),
+ new ParserOutput()
+ );
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter->expects( $this->any() )
+ ->method( 'addFromArray' )
+ ->will( $this->returnSelf() );
+
+ $messageFormatter->expects( $this->once() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $messageFormatter->expects( $this->once() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new ConceptParserFunction( $parserData, $messageFormatter );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->parse( [] )
+ );
+ }
+
+ /**
+ * @dataProvider queryParameterProvider
+ */
+ public function testParse( array $params, array $expected ) {
+
+ $parserData = $this->applicationFactory->newParserData(
+ Title::newFromText( __METHOD__, SMW_NS_CONCEPT ),
+ new ParserOutput()
+ );
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter->expects( $this->any() )
+ ->method( 'addFromArray' )
+ ->will( $this->returnSelf() );
+
+ $instance = new ConceptParserFunction( $parserData, $messageFormatter );
+ $instance->parse( $params );
+
+ $this->assertCount(
+ $expected['propertyCount'],
+ $parserData->getSemanticData()->getProperties()
+ );
+
+ foreach ( $parserData->getSemanticData()->getProperties() as $property ){
+
+ if ( $property->getKey() !== '_CONC' ) {
+ continue;
+ }
+
+ foreach ( $parserData->getSemanticData()->getPropertyValues( $property ) as $dataItem ) {
+ $this->assertEquals( $expected['conceptQuery'], $dataItem->getConceptQuery() );
+ $this->assertEquals( $expected['conceptDocu'], $dataItem->getDocumentation() );
+ $this->assertEquals( $expected['conceptSize'], $dataItem->getSize() );
+ $this->assertEquals( $expected['conceptDepth'], $dataItem->getDepth() );
+ }
+ }
+ }
+
+ public function queryParameterProvider() {
+
+ $provider = [];
+
+ // #0
+ // {{#concept: [[Modification date::+]]
+ // }}
+ $provider[] = [
+ [
+ '[[Modification date::+]]'
+ ],
+ [
+ 'result' => true,
+ 'propertyCount' => 2,
+ 'conceptQuery' => '[[Modification date::+]]',
+ 'conceptDocu' => '',
+ 'conceptSize' => 1,
+ 'conceptDepth' => 1,
+ ]
+ ];
+
+ // #1
+ // {{#concept: [[Modification date::+]]
+ // |Foooooooo
+ // }}
+ $provider[] = [
+ [
+ '[[Modification date::+]]',
+ 'Foooooooo'
+ ],
+ [
+ 'result' => true,
+ 'propertyCount' => 2,
+ 'conceptQuery' => '[[Modification date::+]]',
+ 'conceptDocu' => 'Foooooooo',
+ 'conceptSize' => 1,
+ 'conceptDepth' => 1,
+ ]
+ ];
+
+ // #2 (includes Parser object)
+ $parser = UtilityFactory::getInstance()->newParserFactory()->newFromTitle( Title::newFromText( __METHOD__ ) );
+
+ $provider[] = [
+ [
+ $parser,
+ '[[Modification date::+]]',
+ 'Foooooooo'
+ ],
+ [
+ 'result' => true,
+ 'propertyCount' => 2,
+ 'conceptQuery' => '[[Modification date::+]]',
+ 'conceptDocu' => 'Foooooooo',
+ 'conceptSize' => 1,
+ 'conceptDepth' => 1,
+ ]
+ ];
+
+ return $provider;
+
+ }
+
+ public function namespaceDataProvider() {
+ return [
+ [ NS_MAIN ],
+ [ NS_HELP ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DeclareParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DeclareParserFunctionTest.php
new file mode 100644
index 00000000..38e2c730
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DeclareParserFunctionTest.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use SMW\ApplicationFactory;
+use SMW\ParserFunctions\DeclareParserFunction;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\DeclareParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class DeclareParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\DeclareParserFunction',
+ new DeclareParserFunction( $parserData )
+ );
+ }
+
+ /**
+ * @dataProvider argumentProvider
+ */
+ public function testParse( $args, $expected ) {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $ppframe = $this->getMockBuilder( '\PPFrame' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $ppframe->expects( $this->any() )
+ ->method( 'isTemplate' )
+ ->will( $this->returnValue( true ) );
+
+ $ppframe->expects( $this->any() )
+ ->method( 'expand' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $ppframe->expects( $this->any() )
+ ->method( 'getArgument' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new DeclareParserFunction( $parserData );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->parse( $ppframe, $args )
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function argumentProvider() {
+
+ $provider[] = [
+ [ 'Has foo=Bar' ],
+ [
+ 'propertyLabel' => [ 'Has foo' ],
+ 'propertyValues' => [ 'Bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DocumentationParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DocumentationParserFunctionTest.php
new file mode 100644
index 00000000..a54eadf5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/DocumentationParserFunctionTest.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParamProcessor\ProcessedParam;
+use ParamProcessor\ProcessingResult;
+use SMW\ParserFunctions\DocumentationParserFunction;
+
+/**
+ * @covers \SMW\ParserFunctions\DocumentationParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DocumentationParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testHandle() {
+
+ $instance = new DocumentationParserFunction();
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $processedParam = $this->getMockBuilder( ProcessedParam::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language = $this->getMockBuilder( ProcessedParam::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $language->expects( $this->any() )
+ ->method( 'getValue' )
+ ->will( $this->returnValue( 'en' ) );
+
+ $processingResult = $this->getMockBuilder( ProcessingResult::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $processingResult->expects( $this->any() )
+ ->method( 'getParameters' )
+ ->will( $this->returnValue( [
+ 'language' => $language,
+ 'format' => $processedParam,
+ 'parameters' => $processedParam ]
+ ) );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->handle( $parser, $processingResult )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ExpensiveFuncExecutionWatcherTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ExpensiveFuncExecutionWatcherTest.php
new file mode 100644
index 00000000..98e72165
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ExpensiveFuncExecutionWatcherTest.php
@@ -0,0 +1,149 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use SMW\ParserFunctions\ExpensiveFuncExecutionWatcher;
+
+/**
+ * @covers \SMW\ParserFunctions\ExpensiveFuncExecutionWatcher
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ExpensiveFuncExecutionWatcherTest extends \PHPUnit_Framework_TestCase {
+
+ private $parserData;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\ExpensiveFuncExecutionWatcher',
+ new ExpensiveFuncExecutionWatcher( $this->parserData )
+ );
+ }
+
+ public function testHasReachedExpensiveLimit() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 100 ) );
+
+ $this->parserData->expects( $this->once() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $instance = new ExpensiveFuncExecutionWatcher(
+ $this->parserData
+ );
+
+ $instance->setExpensiveExecutionLimit( 1 );
+
+ $this->assertTrue(
+ $instance->hasReachedExpensiveLimit( $query )
+ );
+ }
+
+ public function testIncrementExpensiveCountOnExsitingCounter() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->will( $this->returnValue( 42 ) );
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'setExtensionData' )
+ ->with(
+ $this->equalTo( ExpensiveFuncExecutionWatcher::EXPENSIVE_COUNTER ),
+ $this->equalTo( 43 ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 100 ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getOption' )
+ ->will( $this->returnValue( 100 ) );
+
+ $this->parserData->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $instance = new ExpensiveFuncExecutionWatcher(
+ $this->parserData
+ );
+
+ $instance->setExpensiveThreshold( 1 );
+ $instance->setExpensiveExecutionLimit( 1 );
+
+ $instance->incrementExpensiveCount( $query );
+ }
+
+ public function testIncrementExpensiveCountOnNull() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'setExtensionData' )
+ ->with(
+ $this->equalTo( ExpensiveFuncExecutionWatcher::EXPENSIVE_COUNTER ),
+ $this->equalTo( 1 ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 100 ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getOption' )
+ ->will( $this->returnValue( 100 ) );
+
+ $this->parserData->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $parserOutput ) );
+
+ $instance = new ExpensiveFuncExecutionWatcher(
+ $this->parserData
+ );
+
+ $instance->setExpensiveThreshold( 1 );
+ $instance->setExpensiveExecutionLimit( 1 );
+
+ $instance->incrementExpensiveCount( $query );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/InfoParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/InfoParserFunctionTest.php
new file mode 100644
index 00000000..99f86f02
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/InfoParserFunctionTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use SMW\ParserFunctions\InfoParserFunction;
+
+/**
+ * @covers \SMW\ParserFunctions\InfoParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class InfoParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\InfoParserFunction',
+ new InfoParserFunction()
+ );
+ }
+
+ public function testHandle() {
+
+ $instance = new InfoParserFunction();
+
+ $parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $processedParam = $this->getMockBuilder( '\ParamProcessor\ProcessedParam' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $processingResult = $this->getMockBuilder( '\ParamProcessor\ProcessingResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $processingResult->expects( $this->any() )
+ ->method( 'getParameters' )
+ ->will( $this->returnValue( [
+ 'message' => $processedParam,
+ 'icon' => $processedParam ] ) );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->handle( $parser, $processingResult )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/RecurringEventsParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/RecurringEventsParserFunctionTest.php
new file mode 100644
index 00000000..d00fa934
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/RecurringEventsParserFunctionTest.php
@@ -0,0 +1,429 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use ReflectionClass;
+use SMW\MessageFormatter;
+use SMW\ParserData;
+use SMW\RecurringEvents;
+use SMW\ParserFunctions\RecurringEventsParserFunction;
+use SMW\ParserParameterProcessor;
+use SMW\Subobject;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\RecurringEventsParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class RecurringEventsParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ RecurringEventsParserFunction::class,
+ new RecurringEventsParserFunction(
+ $parserData,
+ $subobject,
+ $messageFormatter,
+ new RecurringEvents()
+ )
+ );
+ }
+
+ /**
+ * @dataProvider recurringEventsDataProvider
+ */
+ public function testParse( array $params, array $expected ) {
+
+ $recurringEvents = new RecurringEvents();
+ $recurringEvents->setDefaultNumRecurringEvents( 100 );
+ $recurringEvents->setMaxNumRecurringEvents( 100 );
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $instance = new RecurringEventsParserFunction(
+ new ParserData( $title, new ParserOutput() ),
+ new Subobject( $title ),
+ new MessageFormatter( \Language::factory( 'en' ) ),
+ $recurringEvents
+ );
+
+ $result = $instance->parse(
+ new ParserParameterProcessor( $params )
+ );
+
+ $this->assertTrue( $result !== '' ? $expected['errors'] : !$expected['errors'] );
+
+ $this->assertEquals(
+ $expected['parameters'],
+ $recurringEvents->getParameters()
+ );
+ }
+
+ public function recurringEventsDataProvider() {
+
+ $provider = [];
+
+ // #0
+ // {{#set_recurring_event:property=Has birthday
+ // |start=01 Feb 1970
+ // |has title= Birthday
+ // |unit=year
+ // |period=12
+ // |limit=3
+ // }}
+ $provider[] = [
+ [
+ 'property=Has birthday',
+ 'start=01 Feb 1970',
+ 'has title=Birthday',
+ 'unit=month',
+ 'period=12',
+ 'limit=3'
+ ],
+ [
+ 'errors' => false,
+ 'dates' => [
+ '1 February 1970',
+ '1 February 1971',
+ '1 February 1972',
+ '1 February 1973'
+ ],
+ 'property' => [
+ 'Has birthday',
+ 'Has title'
+ ],
+ 'parameters' => [
+ 'has title' => [ 'Birthday' ]
+ ]
+ ]
+ ];
+
+ // #1
+ // {{#set_recurring_event:property=Has birthday
+ // |start=01 Feb 1972 02:00
+ // |has title=Test 12
+ // |unit=week
+ // |period=4
+ // |limit=3
+ // }}
+ $provider[] = [
+ [
+ 'property=Has birthday',
+ 'start=01 Feb 1972 02:00',
+ 'has title=Test 2',
+ 'unit=week',
+ 'period=4',
+ 'limit=3'
+ ],
+ [
+ 'errors' => false,
+ 'dates' => [
+ '1 February 1972 02:00:00',
+ '29 February 1972 02:00:00',
+ '28 March 1972 02:00:00',
+ '25 April 1972 02:00:00'
+ ],
+ 'property' => [
+ 'Has birthday',
+ 'Has title'
+ ],
+ 'parameters' => [
+ 'has title' => [ 'Test 2' ]
+ ]
+ ]
+ ];
+
+ // #2
+ // {{#set_recurring_event:property=Has date
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ $provider[] = [
+ [
+ 'property=Has date',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => false,
+ 'dates' => [
+ '4 January 2010',
+ '11 January 2010',
+ '1 February 2010',
+ 'March 16, 2010',
+ 'March 23, 2010'
+ ],
+ 'property' => 'Has date',
+ 'parameters' => []
+ ]
+ ];
+
+
+ // #3
+ // {{#set_recurring_event:property=Has date
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010|+sep=;
+ // |exclude=January 18, 2010;January 25, 2010|+sep=;
+ // }}
+ $provider[] = [
+ [
+ 'property=Has date',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ '+sep=;', 'exclude=January 18, 2010;January 25, 2010',
+ '+sep=;'
+ ],
+ [
+ 'errors' => false,
+ 'dates' => [
+ '4 January 2010',
+ '11 January 2010',
+ '1 February 2010',
+ 'March 16, 2010',
+ 'March 23, 2010'
+ ],
+ 'property' => 'Has date',
+ 'parameters' => []
+ ]
+ ];
+
+ // #4 Named page reference pointer
+ // {{#set_recurring_event:FooBar
+ // |property=Has birthday
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010|+sep=;
+ // |exclude=January 18, 2010;January 25, 2010|+sep=;
+ // }}
+ $provider[] = [
+ [
+ 'FooBar',
+ 'property=Has birthday',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ '+sep=;', 'exclude=January 18, 2010;January 25, 2010',
+ '+sep=;'
+ ],
+ [
+ 'errors' => false,
+ 'dates' => [
+ '4 January 2010',
+ '11 January 2010',
+ '1 February 2010',
+ 'March 16, 2010',
+ 'March 23, 2010'
+ ],
+ 'property' => 'Has birthday',
+ 'parameters' => []
+ ]
+ ];
+
+ // #5 Simulate first parameter starting being - raising an error
+ // {{#set_recurring_event:-
+ // property=Has date
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ $provider[] = [
+ [
+ '-',
+ 'property=Has date',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => false,
+ 'dates' => [],
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ];
+
+ // #6 Simulate first parameter starting with - raising an error
+ // {{#set_recurring_event:-Foo
+ // property=Has date
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ $provider[] = [
+ [
+ '-Foo',
+ 'property=Has date',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => true,
+ 'dates' => [],
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ];
+
+ // #7 Simulate first parameter starting with a underscore raising an error
+ // {{#set_recurring_event:_FooBar
+ // property=Has date
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ $provider[] = [
+ [
+ '_FooBar',
+ 'property=Has date',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => true,
+ 'dates' => [],
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ];
+
+ // #8 Simulate start date has wrong type
+ // {{#set_recurring_event:property=Has date
+ // |start=???
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ $provider[] = [
+ [
+ 'property=Has date',
+ 'start=???',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => true,
+ 'dates' => [],
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ];
+
+ // #9 Simulate missing start date
+ // {{#set_recurring_event:property=Has date
+ // |start=
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ $provider[] = [
+ [
+ 'property=Has date',
+ 'start=',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => true,
+ 'dates' => [],
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ];
+
+ // #10 Simulate missing property
+ // {{#set_recurring_event:property=
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010|+sep=;
+ // |exclude=January 18, 2010;January 25, 2010|+sep=;
+ // }}
+ $provider[] = [
+ [
+ 'property=',
+ 'start=January 4, 2010',
+ 'unit=week', 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ '+sep=;',
+ 'exclude=January 18, 2010;January 25, 2010',
+ '+sep=;'
+ ],
+ [
+ 'errors' => true,
+ 'dates' => [],
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SectionTagTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SectionTagTest.php
new file mode 100644
index 00000000..08b99d24
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SectionTagTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use SMW\ParserFunctions\SectionTag;
+
+/**
+ * @covers \SMW\ParserFunctions\SectionTag
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SectionTagTest extends \PHPUnit_Framework_TestCase {
+
+ private $frame;
+ private $parser;
+
+ protected function setUp() {
+
+ $this->frame = $this->getMockBuilder( '\PPFrame' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->parser = $this->getMockBuilder( '\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SectionTag::class,
+ new SectionTag( $this->parser, $this->frame )
+ );
+ }
+
+ public function testRegister_Enabled() {
+
+ $this->parser->expects( $this->once() )
+ ->method( 'setHook' );
+
+ $this->assertTrue(
+ SectionTag::register( $this->parser )
+ );
+ }
+
+ public function testRegister_Disabled() {
+
+ $this->parser->expects( $this->never() )
+ ->method( 'setHook' );
+
+ $this->assertFalse(
+ SectionTag::register( $this->parser, false )
+ );
+ }
+
+ public function testParse() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->parser->expects( $this->any() )
+ ->method( 'recursiveTagParse' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->parser->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new SectionTag(
+ $this->parser,
+ $this->frame
+ );
+
+ $args = [];
+
+ $this->assertContains(
+ '<section>Foo</section>',
+ $instance->parse( 'Foo', $args )
+ );
+ }
+
+ public function testParse_PropertyNamespace() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_PROPERTY ) );
+
+ $this->parser->expects( $this->any() )
+ ->method( 'recursiveTagParse' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->parser->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $instance = new SectionTag(
+ $this->parser,
+ $this->frame
+ );
+
+ $args = [];
+
+ $this->assertContains(
+ '<section class="smw-property-specification">Foo</section>',
+ $instance->parse( 'Foo', $args )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SetParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SetParserFunctionTest.php
new file mode 100644
index 00000000..9301a628
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SetParserFunctionTest.php
@@ -0,0 +1,239 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\Renderer\WikitextTemplateRenderer;
+use SMW\ParameterFormatterFactory;
+use SMW\ParserFunctions\SetParserFunction;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\SetParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SetParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $templateRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\WikitextTemplateRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\SetParserFunction',
+ new SetParserFunction( $parserData, $messageFormatter, $templateRenderer )
+ );
+ }
+
+ /**
+ * @dataProvider setParserProvider
+ */
+ public function testParse( array $params ) {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter->expects( $this->any() )
+ ->method( 'addFromArray' )
+ ->will( $this->returnSelf() );
+
+ $messageFormatter->expects( $this->once() )
+ ->method( 'getHtml' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $templateRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\WikitextTemplateRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SetParserFunction(
+ $parserData,
+ $messageFormatter,
+ $templateRenderer
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->parse( ParameterFormatterFactory::newFromArray( $params ) )
+ );
+ }
+
+ /**
+ * @dataProvider setParserProvider
+ */
+ public function testInstantiatedPropertyValues( array $params, array $expected ) {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter->expects( $this->any() )
+ ->method( 'addFromArray' )
+ ->will( $this->returnSelf() );
+
+ $templateRenderer = $this->getMockBuilder( '\SMW\MediaWiki\Renderer\WikitextTemplateRenderer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SetParserFunction(
+ $parserData,
+ $messageFormatter,
+ $templateRenderer
+ );
+
+ $instance->parse( ParameterFormatterFactory::newFromArray( $params ) );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function testTemplateSupport() {
+
+ $params = [ 'Foo=bar', 'Foo=foobar', 'BarFoo=9001', 'template=FooTemplate' ];
+
+ $expected = [
+ 'errors' => 0,
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Foo', 'BarFoo' ],
+ 'propertyValues' => [ 'Bar', '9001', 'Foobar' ]
+ ];
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter->expects( $this->any() )
+ ->method( 'addFromArray' )
+ ->will( $this->returnSelf() );
+
+ $templateRenderer = new WikitextTemplateRenderer();
+
+ $instance = new SetParserFunction(
+ $parserData,
+ $messageFormatter,
+ $templateRenderer
+ );
+
+ $instance->parse(
+ ParameterFormatterFactory::newFromArray( $params )
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()
+ );
+ }
+
+ public function setParserProvider() {
+
+ // #0 Single data set
+ // {{#set:
+ // |Foo=bar
+ // }}
+ $provider[] = [
+ [ 'Foo=bar' ],
+ [
+ 'errors' => 0,
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => 'Bar'
+ ]
+ ];
+
+ // #1 Empty data set
+ // {{#set:
+ // |Foo=
+ // }}
+ $provider[] = [
+ [ 'Foo=' ],
+ [
+ 'errors' => 0,
+ 'propertyCount' => 0,
+ 'propertyLabels' => '',
+ 'propertyValues' => ''
+ ]
+ ];
+
+ // #2 Multiple data set
+ // {{#set:
+ // |BarFoo=9001
+ // |Foo=bar
+ // }}
+ $provider[] = [
+ [ 'Foo=bar', 'BarFoo=9001' ],
+ [
+ 'errors' => 0,
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Foo', 'BarFoo' ],
+ 'propertyValues' => [ 'Bar', '9001' ]
+ ]
+ ];
+
+ // #3 Multiple data set with an error record
+ // {{#set:
+ // |_Foo=9001 --> will raise an error
+ // |Foo=bar
+ // }}
+ $provider[] = [
+ [ 'Foo=bar', '_Foo=9001' ],
+ [
+ 'errors' => 1,
+ 'propertyCount' => 2,
+ 'strictPropertyValueMatch' => false,
+ 'propertyKeys' => [ 'Foo', '_ERRC' ],
+ 'propertyValues' => [ 'Bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ShowParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ShowParserFunctionTest.php
new file mode 100644
index 00000000..45a6ee9c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/ShowParserFunctionTest.php
@@ -0,0 +1,287 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use SMW\ApplicationFactory;
+use SMW\ParserFunctions\AskParserFunction;
+use SMW\ParserFunctions\ShowParserFunction;
+use SMW\Tests\TestEnvironment;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\ShowParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ShowParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $semanticDataValidator;
+ private $messageFormatter;
+ private $circularReferenceGuard;
+ private $expensiveFuncExecutionWatcher;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+
+ $this->testEnvironment->addConfiguration( 'smwgQueryProfiler', true );
+ $this->testEnvironment->addConfiguration( 'smwgQueryResultCacheType', false );
+ $this->testEnvironment->addConfiguration( 'smwgQFilterDuplicates', false );
+
+ $this->messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->expensiveFuncExecutionWatcher = $this->getMockBuilder( '\SMW\ParserFunctions\ExpensiveFuncExecutionWatcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->expensiveFuncExecutionWatcher->expects( $this->any() )
+ ->method( 'hasReachedExpensiveLimit' )
+ ->will( $this->returnValue( false ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getQueryResult' )
+ ->will( $this->returnValue( $queryResult ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $askParserFunction = new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\ShowParserFunction',
+ new ShowParserFunction( $askParserFunction )
+ );
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testParse( array $params, array $expected ) {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new ShowParserFunction(
+ new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ )
+ );
+
+ $result = $instance->parse( $params );
+
+ if ( $expected['output'] === '' ) {
+ $this->assertEmpty( $result, "Actual result: \"$result\"\n" );
+ } else {
+ $this->assertContains( $expected['output'], $result );
+ }
+ }
+
+ public function testIsQueryDisabled() {
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->messageFormatter->expects( $this->any() )
+ ->method( 'addFromKey' )
+ ->will( $this->returnSelf() );
+
+ $this->messageFormatter->expects( $this->once() )
+ ->method( 'getHtml' );
+
+ $instance = new ShowParserFunction(
+ new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ )
+ );
+
+ $instance->isQueryDisabled();
+ }
+
+ /**
+ * @dataProvider queryDataProvider
+ */
+ public function testInstantiatedQueryData( array $params, array $expected ) {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new ShowParserFunction(
+ new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ )
+ );
+
+ $instance->parse( $params );
+
+ foreach ( $parserData->getSemanticData()->getSubSemanticData() as $containerSemanticData ){
+ $this->assertInstanceOf( 'SMWContainerSemanticData', $containerSemanticData );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $containerSemanticData
+ );
+ }
+ }
+
+ public function testQueryWithErroneousData() {
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ Title::newFromText( __METHOD__ ),
+ new ParserOutput()
+ );
+
+ $instance = new ShowParserFunction(
+ new AskParserFunction(
+ $parserData,
+ $this->messageFormatter,
+ $this->circularReferenceGuard,
+ $this->expensiveFuncExecutionWatcher
+ )
+ );
+
+ // #2 [[..]] is not acknowledged therefore displays an error message
+ // {{#show: [[File:Fooo]]
+ // |?Modification date
+ // |default=no results
+ // |format=table
+ // }}
+ $params = [
+ '[[File:Fooo]]',
+ '?Modification date',
+ 'default=no results',
+ 'format=table'
+ ];
+
+ $instance->parse( $params );
+
+ $expected = [
+ 'output' => 'class="smwtticon warning"', // lazy content check for the error
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKFO', '_ASKDE', '_ASKSI', '_ASKST' ],
+ 'propertyValues' => [ 'table', 0, 1, '[[:]]' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()->findSubSemanticData( '_QUERY6ee7d0bb3ac4ed35537bcb89914b30ac' )
+ );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_ERRP', '_ERRT' ],
+ ];
+
+ $errorID = null;
+
+ foreach ( $parserData->getSemanticData()->getSubSemanticData() as $subSemanticData ) {
+ if ( strpos( $subSemanticData->getSubject()->getSubobjectName(), '_ERR' ) !== false ) {
+ $errorID = $subSemanticData->getSubject()->getSubobjectName();
+ break;
+ }
+ }
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserData->getSemanticData()->findSubSemanticData( $errorID )
+ );
+ }
+
+ public function queryDataProvider() {
+
+ $provider = [];
+
+ // #0
+ // {{#show: Foo-show
+ // |?Modification date
+ // }}
+ $provider[] = [
+ [
+ 'Foo-show',
+ '?Modification date',
+ ],
+ [
+ 'output' => '',
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKFO', '_ASKDE', '_ASKSI', '_ASKST' ],
+ 'propertyValues' => [ 'list', 0, 1, '[[:Foo]]' ]
+ ]
+ ];
+
+ // #1
+ // {{#show: Help:Bar
+ // |?Modification date
+ // |default=no results
+ // }}
+ $provider[] = [
+ [
+ 'Help:Bar',
+ '?Modification date',
+ 'default=no results'
+ ],
+ [
+ 'output' => 'no results',
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_ASKFO', '_ASKDE', '_ASKSI', '_ASKST' ],
+ 'propertyValues' => [ 'list', 0, 1, '[[:Help:Bar]]' ]
+ ]
+ ];
+
+ return $provider;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php
new file mode 100644
index 00000000..7ac42795
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserFunctions/SubobjectParserFunctionTest.php
@@ -0,0 +1,738 @@
+<?php
+
+namespace SMW\Tests\ParserFunctions;
+
+use ParserOutput;
+use SMW\DIProperty;
+use SMW\Localizer;
+use SMW\MessageFormatter;
+use SMW\ParserData;
+use SMW\ParserFunctions\SubobjectParserFunction;
+use SMW\ParserParameterFormatter;
+use SMW\Subobject;
+use SMW\Tests\Utils\UtilityFactory;
+use SMW\Tests\PHPUnitCompat;
+use Title;
+
+/**
+ * @covers \SMW\ParserFunctions\SubobjectParserFunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SubobjectParserFunctionTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $parserData = $this->getMockBuilder( '\SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $messageFormatter = $this->getMockBuilder( '\SMW\MessageFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ParserFunctions\SubobjectParserFunction',
+ new SubobjectParserFunction(
+ $parserData,
+ $subobject,
+ $messageFormatter
+ )
+ );
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testParse( array $parameters, array $expected ) {
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $result = $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $this->assertInternalType(
+ 'string',
+ $result
+ );
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testInstantiatedSubobject( array $parameters, array $expected ) {
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $this->assertContains(
+ $expected['identifier'],
+ $subobject->getSubobjectId()
+ );
+ }
+
+ /**
+ * @dataProvider firstElementDataProvider
+ */
+ public function testFirstElementAsPropertyLabel( $isEnabled , array $parameters, array $expected ) {
+
+ $parserOutput = new ParserOutput();
+ $title = Title::newFromText( __METHOD__ );
+ $subobject = new Subobject( $title );
+
+ $instance = $this->acquireInstance( $subobject, $parserOutput );
+ $instance->useFirstElementAsPropertyLabel( $isEnabled );
+
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ // If it is enabled only check for the first character {0} that should
+ // contain '_' as the rest is going to be an unknown hash value
+ $id = $subobject->getSubobjectId();
+ $this->assertEquals( $expected['identifier'], $isEnabled ? $id{0} : $id );
+
+ $parserData = new ParserData( $title, $parserOutput );
+
+ // Add generated title text as property value due to the auto reference
+ // setting
+ $expected['propertyValues'][] = $title->getText();
+
+ foreach ( $parserData->getSemanticData()->getSubSemanticData() as $containerSemanticData ){
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $containerSemanticData
+ );
+ }
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testInstantiatedPropertyValues( array $parameters, array $expected ) {
+ $this->setupInstanceAndAssertSemanticData(
+ $parameters,
+ $expected
+ );
+ }
+
+ /**
+ * @dataProvider tokuFixedParameterProvider
+ */
+ public function testSortKeyAnnotation( array $parameters, array $expected ) {
+ $this->setupInstanceAndAssertSemanticData(
+ $parameters,
+ $expected
+ );
+ }
+
+ public function testSubobjectIdStabilityForFixedSetOfParameters() {
+
+ $parameters = [
+ 'Foo=Bar'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ // Expected to be stable for PHP and HHVM as well
+ $this->assertEquals(
+ '_be96d37a4d7c35be8673cb4229b8fdec',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testParametersOnBeingSorted() {
+
+ $parameters = [
+ 'Foo=Foobar, Bar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent(
+ true
+ );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parameters )
+ );
+
+ $this->assertEquals(
+ '_c0bea380739b21578cdcf28ed5d4cfd3',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testParametersOnBeingSortedWithRevertedValueOrderProducesSameHash() {
+
+ $parameters = [
+ 'Foo=Bar, Foobar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent(
+ true
+ );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parameters )
+ );
+
+ $this->assertEquals(
+ '_c0bea380739b21578cdcf28ed5d4cfd3',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testParametersIsNotSorted() {
+
+ $parameters = [
+ 'Foo=Foobar, Bar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent(
+ false
+ );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parameters )
+ );
+
+ // Expected to be stable for PHP and HHVM as well
+ $this->assertEquals(
+ '_ec7323184d89fe1409b5cfaf09950a95',
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testCreateSameIdForNormalizedParametersWithEnabledCapitalLinks() {
+
+ $title = Title::newFromText( __METHOD__ );
+
+ $parametersOne = [
+ 'Foo=Bar',
+ 'Has foo=bar,Foo',
+ '+sep=,'
+ ];
+
+ $parametersTwo = [
+ 'foo=Bar',
+ 'has foo=Foo,bar',
+ '+sep=,'
+ ];
+
+ $subobject = new Subobject( $title );
+
+ $instance = $this->acquireInstance( $subobject );
+
+ $instance->isComparableContent( true );
+ $instance->isCapitalLinks( true );
+
+ $instance->parse(
+ new ParserParameterFormatter( $parametersOne )
+ );
+
+ $id = $subobject->getSubobjectId();
+
+ $instance->parse(
+ new ParserParameterFormatter( $parametersTwo )
+ );
+
+ $this->assertEquals(
+ $id,
+ $subobject->getSubobjectId()
+ );
+ }
+
+ public function testRestrictionOnTooShortFirstPartWhenDotIsUsedForUserNamedSubobject() {
+
+ // #1299, #1302
+ // Has dot restriction
+ // {{#subobject:foo.bar
+ // |Date=Foo
+ // }}
+ $parameters = [
+ 'foo.bar',
+ 'Date=Foo'
+ ];
+
+ $subobject = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $instance = $this->acquireInstance( $subobject );
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $this->setExpectedException( '\SMW\Exception\SubSemanticDataException' );
+ $subobject->getSubobjectId();
+ }
+
+ protected function setupInstanceAndAssertSemanticData( array $parameters, array $expected ) {
+
+ $title = isset( $expected['embeddedTitle'] ) ? $expected['embeddedTitle'] : __METHOD__;
+
+ $parserOutput = new ParserOutput();
+ $title = Title::newFromText( $title );
+ $subobject = new Subobject( $title );
+
+ $instance = $this->acquireInstance(
+ $subobject,
+ $parserOutput
+ );
+
+ $instance->parse( new ParserParameterFormatter( $parameters ) );
+
+ $parserData = new ParserData(
+ $title,
+ $parserOutput
+ );
+
+ $subSemanticData = $parserData->getSemanticData()->getSubSemanticData();
+
+ if ( $expected['propertyCount'] == 0 ) {
+ $this->assertEmpty(
+ $subSemanticData
+ );
+ }
+
+ foreach ( $subSemanticData as $key => $semanticData ){
+
+ if ( strpos( $semanticData->getSubject()->getSubobjectName(), '_ERR' ) !== false ) {
+ continue;
+ }
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $semanticData
+ );
+ }
+ }
+
+ public function parameterDataProvider() {
+
+ $helpNS = Localizer::getInstance()->getNamespaceTextById( NS_HELP );
+
+ $provider = [];
+
+ #0 Anonymous identifier
+ // {{#subobject:
+ // |Foo=bar
+ // }}
+ $provider[] = [
+ [ '', 'Foo=bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => '_',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => 'Bar'
+ ]
+ ];
+
+ #1 Anonymous identifier
+ // {{#subobject:-
+ // |Foo=1001 9009
+ // }}
+ $provider[] = [
+ [ '-', 'Foo=1001 9009' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => '_',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => '1001 9009'
+ ]
+ ];
+
+ #2 Named identifier
+ // {{#subobject:FooBar
+ // |FooBar=Bar foo
+ // }}
+ $provider[] = [
+ [ 'FooBar', 'FooBar=Bar foo' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'FooBar',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'FooBar',
+ 'propertyValues' => 'Bar foo'
+ ]
+ ];
+
+ #3 Named identifier
+ // {{#subobject:Foo bar
+ // |Foo=Help:Bar
+ // }}
+ $provider[] = [
+ [ 'Foo bar', 'Foo=Help:Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => "$helpNS:Bar"
+ ]
+ ];
+
+ #4 Named identifier
+ // {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar_foo',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Bar',
+ 'propertyValues' => 'Foo Bar'
+ ]
+ ];
+
+ #5 Named identifier
+ // {{#subobject: Foo bar foo
+ // |状æ³=超やã°ã„
+ // |Bar=http://www.semantic-mediawiki.org/w/index.php?title=Subobject
+ // }}
+ $provider[] = [
+ [
+ ' Foo bar foo ',
+ '状æ³=超やã°ã„',
+ 'Bar=http://www.semantic-mediawiki.org/w/index.php?title=Subobject' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar_foo',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ '状æ³', 'Bar' ],
+ 'propertyValues' => [ '超やã°ã„', 'Http://www.semantic-mediawiki.org/w/index.php?title=Subobject' ]
+ ]
+ ];
+
+ #6 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |Modification date=foo Bar
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Bar=foo Bar', 'Modification date=foo Bar' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ 'Bar', '_ERRC' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ #7 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |-Foo=foo Bar
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Bar=foo Bar', '-Foo=foo Bar' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ 'Bar', '_ERRC' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ // An empty subobject is not being classified as valid (to create an object)
+ #8 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |Modification date=1 Jan 1970
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Modification date=1 Jan 1970' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ERRC' ]
+ ]
+ ];
+
+ // Get the right language for an error object
+ $diPropertyError = new DIProperty( DIProperty::TYPE_ERROR );
+
+ #9 {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // |Date=Foo
+ // }}
+ $provider[] = [
+ [ ' Foo bar foo ', 'Date=Foo' ],
+ [
+ 'hasErrors' => true,
+ 'identifier' => 'Foo_bar_foo',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ERRC' ]
+ ]
+ ];
+
+ // Not dot restriction
+ #10 {{#subobject:foobar.bar
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ [ 'foobar.bar', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'foobar.bar',
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ 'Bar' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function firstElementDataProvider() {
+
+ $provider = [];
+
+ // #0 / asserting that a named identifier was turned into an anonymous id
+ // {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ true,
+ [ ' Foo bar foo ', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => '_',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Bar', 'Foo bar foo' ],
+ 'propertyValues' => [ 'Foo Bar' ] // additional value is added during runtime
+ ]
+ ];
+
+ // #1 / asserting the validity of the named identifier
+ // {{#subobject: Foo bar foo
+ // |Bar=foo Bar
+ // }}
+ $provider[] = [
+ false,
+ [ ' Foo bar foo ', 'Bar=foo Bar' ],
+ [
+ 'hasErrors' => false,
+ 'identifier' => 'Foo_bar_foo',
+ 'propertyCount' => 1,
+ 'propertyLabels' => [ 'Bar' ],
+ 'propertyValues' => [ 'Foo Bar' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function tokuFixedParameterProvider() {
+
+ $provider = [];
+
+ // #0 @sortkey
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@sortkey=9999
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@sortkey=9999'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( 'Bar' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar',
+ '9999'
+ ]
+ ]
+ ];
+
+ // #1 @sortkey being empty
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@sortkey=
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@sortkey='
+ ],
+ [
+ 'propertyCount' => 1,
+ 'properties' => [
+ new DIProperty( 'Bar' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar'
+ ]
+ ]
+ ];
+
+ // #2 @category
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@category=1001
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@category=1001'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( 'Bar' ),
+ new DIProperty( '_INST' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar',
+ '1001'
+ ]
+ ]
+ ];
+
+ // #3 @category empty
+ // {{#subobject:
+ // |Bar=foo Bar
+ // |@category=
+ // }}
+ $provider[] = [
+ [
+ 'Bar=foo Bar',
+ '@category='
+ ],
+ [
+ 'propertyCount' => 1,
+ 'properties' => [
+ new DIProperty( 'Bar' )
+ ],
+ 'propertyValues' => [
+ 'Foo Bar'
+ ]
+ ]
+ ];
+
+ // #4 display title to set sortkey
+ // {{#subobject:
+ // |Display title of=Foo
+ // }}
+ $provider[] = [
+ [
+ 'Display title of=Foo'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( '_DTITLE' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [
+ 'Foo'
+ ]
+ ]
+ ];
+
+ // #4 display title to set sortkey
+ // {{#subobject:
+ // |Display title of=Foo
+ // |@sortkey=Bar
+ // }}
+ $provider[] = [
+ [
+ 'Display title of=Foo',
+ '@sortkey=Bar'
+ ],
+ [
+ 'propertyCount' => 2,
+ 'properties' => [
+ new DIProperty( '_DTITLE' ),
+ new DIProperty( '_SKEY' )
+ ],
+ 'propertyValues' => [
+ 'Foo',
+ 'Bar'
+ ]
+ ]
+ ];
+
+ // #5 `Bar` auto-linked with `LinkedToSubjectXY`
+ // {{#subobject:
+ // |@linkWith=Bar
+ // }}
+ $provider[] = [
+ [
+ '@linkWith=Bar'
+ ],
+ [
+ 'embeddedTitle' => 'LinkedToSubjectXY',
+ 'propertyCount' => 1,
+ 'properties' => [
+ new DIProperty( 'Bar' )
+ ],
+ 'propertyValues' => [
+ 'LinkedToSubjectXY'
+ ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return SubobjectParserFunction
+ */
+ private function acquireInstance( Subobject $subobject, ParserOutput $parserOutput = null ) {
+
+ if ( $parserOutput === null ) {
+ $parserOutput = new ParserOutput();
+ }
+
+ return new SubobjectParserFunction(
+ new ParserData( $subobject->getTitle(), $parserOutput ),
+ $subobject,
+ new MessageFormatter( $subobject->getTitle()->getPageLanguage() )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserParameterProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserParameterProcessorTest.php
new file mode 100644
index 00000000..abde651b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ParserParameterProcessorTest.php
@@ -0,0 +1,409 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ParserParameterProcessor;
+
+/**
+ * @covers \SMW\ParserParameterProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParserParameterProcessorTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider parametersDataProvider
+ */
+ public function testCanConstruct( array $parameters ) {
+
+ $this->assertInstanceOf(
+ 'SMW\ParserParameterProcessor',
+ new ParserParameterProcessor( $parameters )
+ );
+ }
+
+ /**
+ * @dataProvider parametersDataProvider
+ */
+ public function testGetRaw( array $parameters ) {
+
+ $instance = new ParserParameterProcessor( $parameters );
+
+ $this->assertEquals(
+ $parameters,
+ $instance->getRaw()
+ );
+ }
+
+ public function testSetParameters() {
+
+ $instance = new ParserParameterProcessor();
+
+ $parameters = [
+ 'Foo' => 'Bar'
+ ];
+
+ $instance->setParameters( $parameters );
+
+ $this->assertEquals(
+ $parameters,
+ $instance->toArray()
+ );
+ }
+
+ public function testAddAndRemoveParameter() {
+
+ $instance = new ParserParameterProcessor();
+
+ $instance->addParameter(
+ 'Foo', 'Bar'
+ );
+
+ $this->assertEquals(
+ [ 'Foo' => [ 'Bar' ] ],
+ $instance->toArray()
+ );
+
+ $instance->removeParameterByKey( 'Foo' );
+
+ $this->assertFalse(
+ $instance->hasParameter( 'Foo' )
+ );
+ }
+
+ public function testSetParameter() {
+
+ $instance = new ParserParameterProcessor();
+
+ $instance->setParameter(
+ 'Foo', []
+ );
+
+ $this->assertEmpty(
+ $instance->toArray()
+ );
+
+ $instance->setParameter(
+ 'Foo', [ 'Bar' ]
+ );
+
+ $this->assertEquals(
+ [ 'Foo' => [ 'Bar' ] ],
+ $instance->toArray()
+ );
+ }
+
+ public function testSort() {
+
+ $a = [
+ 'Has test 3=One,Two,Three',
+ '+sep',
+ 'Has test 4=Four'
+ ];
+
+ $instance = new ParserParameterProcessor(
+ $a
+ );
+
+ $paramsA = $instance->toArray();
+ $instance->sort( $paramsA );
+
+ $b = [
+ 'Has test 4=Four',
+ 'Has test 3=Two,Three,One',
+ '+sep',
+ ];
+
+ $instance = new ParserParameterProcessor(
+ $b
+ );
+
+ $paramsB = $instance->toArray();
+
+ $instance->sort( $paramsB );
+
+ $this->assertEquals(
+ $paramsA,
+ $paramsB
+ );
+ }
+
+ /**
+ * @dataProvider parametersDataProvider
+ */
+ public function testToArray( array $parameters, array $expected ) {
+
+ $instance = new ParserParameterProcessor( $parameters );
+
+ $this->assertEquals(
+ $expected,
+ $instance->toArray()
+ );
+ }
+
+ /**
+ * @dataProvider firstParameterDataProvider
+ */
+ public function testGetFirst( array $parameters, array $expected ) {
+
+ $instance = new ParserParameterProcessor( $parameters );
+
+ $this->assertEquals(
+ $expected['identifier'],
+ $instance->getFirst()
+ );
+ }
+
+ public function parametersDataProvider() {
+
+ // {{#...:
+ // |Has test 1=One
+ // }}
+ $provider[] = [
+ [
+ 'Has test 1=One'
+ ],
+ [
+ 'Has test 1' => [ 'One' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Has test 1=One
+ // }}
+ $provider[] = [
+ [
+ [ 'Foo' ],
+ 'Has test 1=One',
+ ],
+ [
+ 'Has test 1' => [ 'One' ]
+ ],
+ [
+ 'msg' => 'Failed to recognize that only strings can be processed'
+ ]
+ ];
+
+ // {{#...:
+ // |Has test 2=Two
+ // |Has test 2=Three;Four|+sep=;
+ // }}
+ $provider[] = [
+ [
+ 'Has test 2=Two',
+ 'Has test 2=Three;Four',
+ '+sep=;'
+ ],
+ [
+ 'Has test 2' => [ 'Two', 'Three', 'Four' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Has test 3=One,Two,Three|+sep
+ // |Has test 4=Four
+ // }}
+ $provider[] = [
+ [
+ 'Has test 3=One,Two,Three',
+ '+sep',
+ 'Has test 4=Four'
+ ],
+ [
+ 'Has test 3' => [ 'One', 'Two', 'Three' ],
+ 'Has test 4' => [ 'Four' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Has test 5=Test 5-1|Test 5-2|Test 5-3|Test 5-4
+ // |Has test 5=Test 5-5
+ // }}
+ $provider[] = [
+ [
+ 'Has test 5=Test 5-1',
+ 'Test 5-2',
+ 'Test 5-3',
+ 'Test 5-4',
+ 'Has test 5=Test 5-5'
+ ],
+ [
+ 'Has test 5' => [ 'Test 5-1', 'Test 5-2', 'Test 5-3', 'Test 5-4', 'Test 5-5' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Has test 6=1+2+3|+sep=+
+ // |Has test 7=7
+ // |Has test 8=9,10,11,|+sep=
+ // }}
+ $provider[] = [
+ [
+ 'Has test 6=1+2+3',
+ '+sep=+',
+ 'Has test 7=7',
+ 'Has test 8=9,10,11,',
+ '+sep='
+ ],
+ [
+ 'Has test 6' => [ '1', '2', '3'],
+ 'Has test 7' => [ '7' ],
+ 'Has test 8' => [ '9', '10', '11' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Has test 9=One,Two,Three|+sep=;
+ // |Has test 10=Four
+ // }}
+ $provider[] = [
+ [
+ 'Has test 9=One,Two,Three',
+ '+sep=;',
+ 'Has test 10=Four'
+ ],
+ [
+ 'Has test 9' => [ 'One,Two,Three' ],
+ 'Has test 10' => [ 'Four' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Has test 11=Test 5-1|Test 5-2|Test 5-3|Test 5-4
+ // |Has test 12=Test 5-5
+ // |Has test 11=9,10,11,|+sep=
+ // }}
+ $provider[] = [
+ [
+ 'Has test 11=Test 5-1',
+ 'Test 5-2',
+ 'Test 5-3',
+ 'Test 5-4',
+ 'Has test 12=Test 5-5',
+ 'Has test 11=9,10,11,',
+ '+sep='
+ ],
+ [
+ 'Has test 11' => [ 'Test 5-1', 'Test 5-2', 'Test 5-3', 'Test 5-4', '9', '10', '11' ],
+ 'Has test 12' => [ 'Test 5-5' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Has test url=http://www.semantic-mediawiki.org/w/index.php?title=Subobject;http://www.semantic-mediawiki.org/w/index.php?title=Set|+sep=;
+ // }}
+ $provider[] = [
+ [
+ 'Has test url=http://www.semantic-mediawiki.org/w/index.php?title=Subobject;http://www.semantic-mediawiki.org/w/index.php?title=Set',
+ '+sep=;'
+ ],
+ [
+ 'Has test url' => [ 'http://www.semantic-mediawiki.org/w/index.php?title=Subobject', 'http://www.semantic-mediawiki.org/w/index.php?title=Set' ]
+ ]
+ ];
+
+ // {{#...:
+ // |Foo=123|345|456|+pipe
+ // }}
+ $provider[] = [
+ [
+ 'Foo=123',
+ '345',
+ '456',
+ '+pipe'
+ ],
+ [
+ 'Foo' => [ '123|345|456' ]
+ ]
+ ];
+
+ // {{#...:
+ // |@json={ "Foo": 123}
+ // }}
+ $provider[] = [
+ [
+ '@json={ "Foo": 123}'
+ ],
+ [
+ 'Foo' => [ '123' ]
+ ]
+ ];
+
+ // {{#...:
+ // |@json={ "Foo": [123, 456] }
+ // }}
+ $provider[] = [
+ [
+ '@json={ "Foo": [123, 456] }'
+ ],
+ [
+ 'Foo' => [ '123', '456' ]
+ ]
+ ];
+
+ // Error
+ // {{#...:
+ // |@json={ "Foo": [123, 456] }
+ // }}
+ $provider[] = [
+ [
+ '@json={ Foo: [123, 456] }'
+ ],
+ [
+ '@json' => [ '{ Foo: [123, 456] }' ]
+ ]
+ ];
+
+ // Avoid spaces on individual values
+ // {{#...:
+ // |Has test=One; Two|+sep=;
+ // }}
+ $provider[] = [
+ [
+ 'Has test=One; Two',
+ '+sep=;'
+ ],
+ [
+ 'Has test' => [ 'One', 'Two' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function firstParameterDataProvider() {
+
+ // {{#subobject:
+ // |Has test 1=One
+ // }}
+ $provider[] = [
+ [ '', 'Has test 1=One'],
+ [ 'identifier' => null ]
+ ];
+
+ // {{#set_recurring_event:Foo
+ // |Has test 2=Two
+ // |Has test 2=Three;Four|+sep=;
+ // }}
+ $provider[] = [
+ [ 'Foo' , 'Has test 2=Two', 'Has test 2=Three;Four', '+sep=;' ],
+ [ 'identifier' => 'Foo' ]
+ ];
+
+ // {{#subobject:-
+ // |Has test 2=Two
+ // |Has test 2=Three;Four|+sep=;
+ // }}
+ $provider[] = [
+ [ '-', 'Has test 2=Two', 'Has test 2=Three;Four', '+sep=;' ],
+ [ 'identifier' => '-' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PermissionPthValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PermissionPthValidatorTest.php
new file mode 100644
index 00000000..bdadbe40
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PermissionPthValidatorTest.php
@@ -0,0 +1,484 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\PermissionPthValidator;
+use Title;
+
+/**
+ * @covers \SMW\PermissionPthValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class PermissionPthValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $protectionValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->protectionValidator = $this->getMockBuilder( '\SMW\Protection\ProtectionValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PermissionPthValidator::class,
+ new PermissionPthValidator( $this->protectionValidator )
+ );
+ }
+
+ public function testGrantPermissionToMainNamespace() {
+
+ $title = Title::newFromText( 'Foo', NS_MAIN );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertTrue(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+
+ $this->assertEmpty(
+ $result
+ );
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testToReturnFalseOnMwNamespacePermissionCheck( $title, $permission, $action, $expected ) {
+
+ $this->protectionValidator ->expects( $this->any() )
+ ->method( 'hasEditProtection' )
+ ->will( $this->returnValue( true ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'isAllowed' )
+ ->with( $this->equalTo( $permission ) )
+ ->will( $this->returnValue( false ) );
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertFalse(
+ $instance->hasUserPermission( $title, $user, $action, $result )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $result
+ );
+ }
+
+ public function testNoUserPermissionOnNamespaceWithEditPermissionCheck() {
+
+ $editProtectionRight = 'Foo';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_PROPERTY ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'hasProtection' )
+ ->will( $this->returnValue( true ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'getEditProtectionRight' )
+ ->will( $this->returnValue( $editProtectionRight ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'hasEditProtectionOnNamespace' )
+ ->will( $this->returnValue( true ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'isAllowed' )
+ ->with( $this->equalTo( $editProtectionRight ) )
+ ->will( $this->returnValue( false ) );
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertFalse(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+
+ $this->assertEquals(
+ [ [ 'smw-edit-protection', $editProtectionRight ] ],
+ $result
+ );
+ }
+
+ public function testFalseEditProtectionRightToNeverCheckPermissionOnNonMwNamespace() {
+
+ $editProtectionRight = false;
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( false ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_PROPERTY ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'getEditProtectionRight' )
+ ->will( $this->returnValue( $editProtectionRight ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = '';
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertTrue(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+ }
+
+ public function testNoUserPermissionOnPropertyNamespaceWithCreateProtectionCheck() {
+
+ $createProtectionRight = 'Foo';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( false ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_PROPERTY ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'getCreateProtectionRight' )
+ ->will( $this->returnValue( $createProtectionRight ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertFalse(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+
+ $this->assertEquals(
+ [ [ 'smw-create-protection', null, 'Foo' ] ],
+ $result
+ );
+ }
+
+ public function testNoUserPermissionOnPropertyNamespaceWithCreateProtectionCheck_TitleExists() {
+
+ $createProtectionRight = 'Foo';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_PROPERTY ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'getCreateProtectionRight' )
+ ->will( $this->returnValue( $createProtectionRight ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertFalse(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+
+ $this->assertEquals(
+ [ [ 'smw-create-protection-exists', null, 'Foo' ] ],
+ $result
+ );
+ }
+
+ public function testNoUserPermissionOnCategoryNamespaceWithChangePropagationProtectionCheck() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_CATEGORY ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'hasChangePropagationProtection' )
+ ->will( $this->returnValue( true ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertFalse(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+
+ $this->assertEquals(
+ [
+ [ 'smw-change-propagation-protection' ]
+ ],
+ $result
+ );
+ }
+
+ public function testUserPermissionOnCategoryNamespaceWithChangePropagationProtectionCheck() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_CATEGORY ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'hasChangePropagationProtection' )
+ ->will( $this->returnValue( false ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertTrue(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+
+ $this->assertEquals(
+ [],
+ $result
+ );
+ }
+
+ public function testNoUserEditPermissionOnMissingRight_SchemaNamespace() {
+
+ $editProtectionRight = 'Foo';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_SCHEMA ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'isAllowed' )
+ ->with( $this->equalTo( 'smw-schemaedit' ) )
+ ->will( $this->returnValue( false ) );
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertFalse(
+ $instance->hasUserPermission( $title, $user, 'edit', $result )
+ );
+
+ $this->assertEquals(
+ [
+ [ 'smw-schema-namespace-edit-protection', 'smw-schemaedit' ]
+ ],
+ $result
+ );
+ }
+
+ public function testNoEditcontentmodelPermissionForAnyUser_SchemaNamespace() {
+
+ $editProtectionRight = 'Foo';
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'PermissionTest' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_SCHEMA ) );
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->once() )
+ ->method( 'isAllowed' )
+ ->with( $this->equalTo( 'smw-schemaedit' ) )
+ ->will( $this->returnValue( true ) );
+
+ $result = [];
+
+ $instance = new PermissionPthValidator(
+ $this->protectionValidator
+ );
+
+ $this->assertFalse(
+ $instance->hasUserPermission( $title, $user, 'editcontentmodel', $result )
+ );
+
+ $this->assertEquals(
+ [
+ [ 'smw-schema-namespace-editcontentmodel-disallowed' ]
+ ],
+ $result
+ );
+ }
+
+ public function titleProvider() {
+
+ $provider[] = [
+ Title::newFromText( 'Smw_allows_pattern', NS_MEDIAWIKI ),
+ 'smw-patternedit',
+ 'edit',
+ [ [ 'smw-patternedit-protection', 'smw-patternedit' ] ]
+ ];
+
+ $provider[] = [
+ Title::newFromText( 'Smw_allows_pattern', NS_MEDIAWIKI ),
+ 'smw-patternedit',
+ 'delete',
+ [ [ 'smw-patternedit-protection', 'smw-patternedit' ] ]
+ ];
+
+ $provider[] = [
+ Title::newFromText( 'Smw_allows_pattern', NS_MEDIAWIKI ),
+ 'smw-patternedit',
+ 'move',
+ [ [ 'smw-patternedit-protection', 'smw-patternedit' ] ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PostProcHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PostProcHandlerTest.php
new file mode 100644
index 00000000..30d3ac4d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PostProcHandlerTest.php
@@ -0,0 +1,395 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIWikiPage;
+use SMW\PostProcHandler;
+use SMW\SQLStore\ChangeOp\ChangeDiff;
+
+/**
+ * @covers \SMW\PostProcHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PostProcHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $parserOutput;
+ private $cache;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PostProcHandler::class,
+ new PostProcHandler( $this->parserOutput, $this->cache )
+ );
+ }
+
+ public function testGetHtmlOnCookie() {
+
+ $this->parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_UPDATE ) )
+ ->will( $this->returnValue( [ 'Bar' => true ] ) );
+
+ $instance = new PostProcHandler(
+ $this->parserOutput,
+ $this->cache
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $webRequest->expects( $this->once() )
+ ->method( 'getCookie' )
+ ->will( $this->returnValue( 'FakeCookie' ) );
+
+ $this->assertContains(
+ '<div class="smw-postproc" data-subject="Foo#0##" data-ref="[&quot;Bar&quot;]"></div>',
+ $instance->getHtml( $title, $webRequest )
+ );
+ }
+
+ public function testGetHtmlOnLinksUpdateJournalEntry() {
+
+ $this->cache->expects( $this->atLeastOnce() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( true ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'save' )
+ ->with( $this->stringContains( ':post' ) );
+
+ $this->parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_UPDATE ) )
+ ->will( $this->returnValue( [ 'Bar' => true ] ) );
+
+ $instance = new PostProcHandler(
+ $this->parserOutput,
+ $this->cache
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertContains(
+ '<div class="smw-postproc" data-subject="Foo#0##" data-ref="[&quot;Bar&quot;]"></div>',
+ $instance->getHtml( $title, $webRequest )
+ );
+ }
+
+ public function testGetHtml_CheckQuery() {
+
+ $this->cache->expects( $this->atLeastOnce() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( true ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'save' )
+ ->with( $this->stringContains( ':post' ) );
+
+ $this->parserOutput->expects( $this->at( 0 ) )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_UPDATE ) )
+ ->will( $this->returnValue( [ 'Bar' => true ] ) );
+
+ $this->parserOutput->expects( $this->at( 1 ) )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_CHECK ) )
+ ->will( $this->returnValue( [ 'Foobar' ] ) );
+
+ $instance = new PostProcHandler(
+ $this->parserOutput,
+ $this->cache
+ );
+
+ $instance->setOptions(
+ [
+ 'check-query' => true
+ ]
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertContains(
+ '<div class="smw-postproc" data-subject="Foo#0##" data-ref="[&quot;Bar&quot;]" data-query="[&quot;Foobar&quot;]"></div>',
+ $instance->getHtml( $title, $webRequest )
+ );
+ }
+
+ public function testRunJobs() {
+
+ $instance = new PostProcHandler(
+ $this->parserOutput,
+ $this->cache
+ );
+
+ $instance->setOptions(
+ [
+ 'run-jobs' => [ 'fooJob' => 2 ]
+ ]
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $webRequest->expects( $this->once() )
+ ->method( 'getCookie' )
+ ->will( $this->returnValue( 'FakeCookie' ) );
+
+ $this->assertContains(
+ '<div class="smw-postproc" data-subject="Foo#0##" data-jobs="{&quot;fooJob&quot;:2}"></div>',
+ $instance->getHtml( $title, $webRequest )
+ );
+ }
+
+ /**
+ * @dataProvider validPropertyKey
+ */
+ public function testGetHtmlOnCookieAndValidChangeDiff( $key ) {
+
+ $fieldChangeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\FieldChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $fieldChangeOp->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnValue( 42 ) );
+
+ $tableChangeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\TableChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableChangeOp->expects( $this->any() )
+ ->method( 'getFieldChangeOps' )
+ ->will( $this->returnValue( [ $fieldChangeOp ] ) );
+
+ $changeDiff = new ChangeDiff(
+ DIWikiPage::newFromText( 'Foo' ),
+ [ $tableChangeOp ],
+ [],
+ [ $key => 42 ]
+ );
+
+ $this->cache->expects( $this->at( 0 ) )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( $changeDiff->serialize() ) );
+
+ $this->parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_UPDATE ) )
+ ->will( $this->returnValue( [ 'Bar' ] ) );
+
+ $instance = new PostProcHandler(
+ $this->parserOutput,
+ $this->cache
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $webRequest = $this->getMockBuilder( '\WebRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $webRequest->expects( $this->once() )
+ ->method( 'getCookie' )
+ ->will( $this->returnValue( 'FakeCookie' ) );
+
+ $this->assertContains(
+ '<div class="smw-postproc" data-subject="Foo#0##" data-ref="[0]"></div>',
+ $instance->getHtml( $title, $webRequest )
+ );
+ }
+
+ /**
+ * @dataProvider queryProvider
+ */
+ public function testAddUpdate( $gExtensionData, $sExtensionData, $query ) {
+
+ $this->parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_UPDATE ) )
+ ->will( $this->returnValue( $gExtensionData ) );
+
+ $this->parserOutput->expects( $this->once() )
+ ->method( 'setExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_UPDATE ) )
+ ->will( $this->returnValue( $sExtensionData ) );
+
+ $instance = new PostProcHandler(
+ $this->parserOutput,
+ $this->cache
+ );
+
+ $instance->addUpdate( $query );
+ }
+
+ /**
+ * @dataProvider queryProvider
+ */
+ public function testAddCheck( $gExtensionData, $sExtensionData, $query ) {
+
+ $this->parserOutput->expects( $this->once() )
+ ->method( 'getExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_CHECK ) )
+ ->will( $this->returnValue( $gExtensionData ) );
+
+ $this->parserOutput->expects( $this->once() )
+ ->method( 'setExtensionData' )
+ ->with( $this->equalTo( PostProcHandler::POST_EDIT_CHECK ) )
+ ->will( $this->returnValue( $sExtensionData ) );
+
+ $instance = new PostProcHandler(
+ $this->parserOutput,
+ $this->cache
+ );
+
+ $instance->setOptions(
+ [
+ 'check-query' => true
+ ]
+ );
+
+ $instance->addCheck( $query );
+ }
+
+ public function queryProvider() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'toArray' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ $provider[] =[
+ null,
+ [ 'Foo' => true ],
+ $query
+ ];
+
+ $provider[] =[
+ [ 'Bar' => true ],
+ [ 'Bar' => true, 'Foo' => true ],
+ $query
+ ];
+
+ return $provider;
+ }
+
+ public function validPropertyKey() {
+
+ yield [
+ 'Foo'
+ ];
+
+ yield [
+ '_INST'
+ ];
+
+ yield [
+ '_ASK'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ProcessingErrorMsgHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ProcessingErrorMsgHandlerTest.php
new file mode 100644
index 00000000..0c639d83
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/ProcessingErrorMsgHandlerTest.php
@@ -0,0 +1,218 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataItemFactory;
+use SMW\DIWikiPage;
+use SMW\ProcessingErrorMsgHandler;
+
+/**
+ * @covers \SMW\ProcessingErrorMsgHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ProcessingErrorMsgHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $testEnvironment;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\ProcessingErrorMsgHandler',
+ new ProcessingErrorMsgHandler( $subject )
+ );
+ }
+
+ public function testGrepPropertyFromRestrictionErrorMsg() {
+
+ $this->assertNull(
+ ProcessingErrorMsgHandler::grepPropertyFromRestrictionErrorMsg( 'Foo' )
+ );
+ }
+
+ /**
+ * @dataProvider messagesProvider
+ */
+ public function testNormalizeMessages( $messages, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ ProcessingErrorMsgHandler::normalizeAndDecodeMessages( $messages, null, 'en' )
+ );
+
+ $this->assertInternalType(
+ 'string',
+ ProcessingErrorMsgHandler::getMessagesAsString( $messages, null, 'en' )
+ );
+ }
+
+ public function testPush() {
+
+ $instance = new ProcessingErrorMsgHandler(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $container = $this->getMockBuilder( '\SMWDIContainer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'addPropertyObjectValue' )
+ ->with( $this->equalTo( $this->dataItemFactory->newDIProperty( '_ERRC' ) ) );
+
+ $instance->addToSemanticData(
+ $semanticData,
+ $container
+ );
+ }
+
+ public function testGetErrorContainerFromMsg() {
+
+ $instance = new ProcessingErrorMsgHandler(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $property = $this->dataItemFactory->newDIProperty( 'Bar' );
+ $container = $instance->newErrorContainerFromMsg( 'foo', $property );
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $container
+ );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_ERRP', '_ERRT' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $container->getSemanticData()
+ );
+ }
+
+ public function testGetErrorContainerFromMsgWithoutProperty() {
+
+ $instance = new ProcessingErrorMsgHandler(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $container = $instance->newErrorContainerFromMsg( 'foo' );
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ERRT' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $container->getSemanticData()
+ );
+ }
+
+ public function testGetErrorContainerFromDataValue() {
+
+ $instance = new ProcessingErrorMsgHandler(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getErrors', 'getProperty' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Bar' ) ) );
+
+ $container = $instance->newErrorContainerFromDataValue( $dataValue );
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $container
+ );
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_ERRP', '_ERRT' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $container->getSemanticData()
+ );
+ }
+
+ public function messagesProvider() {
+
+ $provider[] = [
+ [],
+ []
+ ];
+
+ $provider[] = [
+ [ 'Foo' ],
+ [ 'Foo' ]
+ ];
+
+ $provider[] = [
+ [ 'Foo', [ 'Bar' ] ],
+ [ 'Foo', 'Bar' ]
+ ];
+
+ $provider[] = [
+ [ 'smw-title', [ 'smw-title' ] ],
+ [ 'Semantic MediaWiki' ]
+ ];
+
+ $provider[] = [
+ [ 'Foo', [ 'Bar', [ 'Bar' ] ] ],
+ [ 'Foo', 'Bar', ]
+ ];
+
+ $provider[] = [
+ [ 'Foo', [ 'Bar', [ 'Bar' ], new \stdClass ] ],
+ [ 'Foo', 'Bar', new \stdClass ]
+ ];
+
+ $provider[] = [
+ [ 'Foo', [ 'Bar', [ 'Bar', new \stdClass ], new \stdClass ], 'Foobar' ],
+ [ 'Foo', 'Bar', new \stdClass, new \stdClass, 'Foobar' ]
+ ];
+
+ $provider[] = [
+ [ 'Foo', [ '[2,"smw-title"]' ] ],
+ [ 'Foo' , 'Semantic MediaWiki' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAliasFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAliasFinderTest.php
new file mode 100644
index 00000000..a5fdf7e3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAliasFinderTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\PropertyAliasFinder;
+
+/**
+ * @covers \SMW\PropertyAliasFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PropertyAliasFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $cache;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+ }
+
+ public function testCanConstruct() {
+
+ $languageIndependentPropertyLabels = [];
+
+ $this->assertInstanceOf(
+ PropertyAliasFinder::class,
+ new PropertyAliasFinder( $this->cache )
+ );
+ }
+
+ public function testFindPropertyAliasById() {
+
+ $propertyAliases = [ 'Bar' => '_Foo' ];
+
+ $instance = new PropertyAliasFinder(
+ $this->cache,
+ $propertyAliases
+ );
+
+ $this->assertEquals(
+ $propertyAliases,
+ $instance->getKnownPropertyAliases()
+ );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->findPropertyAliasById( '_Foo' )
+ );
+ }
+
+ public function testFindPropertyIdByAlias() {
+
+ $canonicalPropertyAliases = [ 'Bar' => '_Foo' ];
+
+ $instance = new PropertyAliasFinder(
+ $this->cache,
+ [],
+ $canonicalPropertyAliases
+ );
+
+ $this->assertEquals(
+ '_Foo',
+ $instance->findPropertyIdByAlias( 'Bar' )
+ );
+ }
+
+ public function testRegisterAliasByFixedLabel() {
+
+ $instance = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance->registerAliasByFixedLabel( '_Foo', 'Bar' );
+
+ $this->assertEquals(
+ '_Foo',
+ $instance->findPropertyIdByAlias( 'Bar' )
+ );
+ }
+
+ public function testGetKnownPropertyAliasesByLanguageCodeCached() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( [ '⧼smw-bar⧽' => '_Foo' ] ) );
+
+ $instance = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance->registerAliasByMsgKey( '_Foo', 'smw-bar' );
+
+ $this->assertEquals(
+ [ '⧼smw-bar⧽' => '_Foo' ],
+ $instance->getKnownPropertyAliasesByLanguageCode( 'en' )
+ );
+ }
+
+ public function testGetKnownPropertyAliasesByLanguageCode() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance->registerAliasByMsgKey( '_Foo', 'smw-bar' );
+
+ $msgKey = version_compare( $GLOBALS['wgVersion'], '1.28', '<' ) ? '<smw-bar>' : '⧼smw-bar⧽' ;
+
+ $this->assertEquals(
+ [ $msgKey => '_Foo' ],
+ $instance->getKnownPropertyAliasesByLanguageCode( 'en' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotatorFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotatorFactoryTest.php
new file mode 100644
index 00000000..11a9d7ab
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotatorFactoryTest.php
@@ -0,0 +1,146 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\PropertyAnnotatorFactory;
+
+/**
+ * @covers \SMW\PropertyAnnotatorFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class PropertyAnnotatorFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotatorFactory',
+ new PropertyAnnotatorFactory()
+ );
+ }
+
+ public function testNewNullPropertyAnnotator() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\NullPropertyAnnotator',
+ $instance->newNullPropertyAnnotator( $semanticData )
+ );
+ }
+
+ public function testNewRedirectPropertyAnnotator() {
+
+ $propertyAnnotator = $this->getMockBuilder( '\SMW\PropertyAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $redirectTargetFinder = $this->getMockBuilder( '\SMW\MediaWiki\RedirectTargetFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\RedirectPropertyAnnotator',
+ $instance->newRedirectPropertyAnnotator( $propertyAnnotator, $redirectTargetFinder )
+ );
+ }
+
+ public function testNewPredefinedPropertyAnnotator() {
+
+ $propertyAnnotator = $this->getMockBuilder( '\SMW\PropertyAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageInfo = $this->getMockBuilder( '\SMW\PageInfo' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\PredefinedPropertyAnnotator',
+ $instance->newPredefinedPropertyAnnotator( $propertyAnnotator, $pageInfo )
+ );
+ }
+
+ public function testNewSortKeyPropertyAnnotator() {
+
+ $propertyAnnotator = $this->getMockBuilder( '\SMW\PropertyAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\SortKeyPropertyAnnotator',
+ $instance->newSortKeyPropertyAnnotator( $propertyAnnotator, 'Foo' )
+ );
+ }
+
+ public function testNewTranslationPropertyAnnotator() {
+
+ $propertyAnnotator = $this->getMockBuilder( '\SMW\PropertyAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\TranslationPropertyAnnotator',
+ $instance->newTranslationPropertyAnnotator( $propertyAnnotator, [] )
+ );
+ }
+
+ public function testNewCategoryPropertyAnnotator() {
+
+ $propertyAnnotator = $this->getMockBuilder( '\SMW\PropertyAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\CategoryPropertyAnnotator',
+ $instance->newCategoryPropertyAnnotator( $propertyAnnotator, [] )
+ );
+ }
+
+ public function testCanConstructMandatoryTypePropertyAnnotator() {
+
+ $propertyAnnotator = $this->getMockBuilder( '\SMW\PropertyAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\MandatoryTypePropertyAnnotator',
+ $instance->newMandatoryTypePropertyAnnotator( $propertyAnnotator )
+ );
+ }
+
+ public function testCanConstructSchemaPropertyAnnotator() {
+
+ $propertyAnnotator = $this->getMockBuilder( '\SMW\PropertyAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\SchemaPropertyAnnotator',
+ $instance->newSchemaPropertyAnnotator( $propertyAnnotator )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/CategoryPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/CategoryPropertyAnnotatorTest.php
new file mode 100644
index 00000000..93c2b073
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/CategoryPropertyAnnotatorTest.php
@@ -0,0 +1,387 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use ParserOutput;
+use SMW\DIWikiPage;
+use SMW\ParserData;
+use SMW\PropertyAnnotators\CategoryPropertyAnnotator;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockTitle;
+
+/**
+ * @covers \SMW\PropertyAnnotators\CategoryPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class CategoryPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->semanticDataFactory = $this->testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new CategoryPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ []
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\CategoryPropertyAnnotator',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider categoriesDataProvider
+ */
+ public function testAddCategoriesAnnotation( array $parameters, array $expected ) {
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( new DIWikiPage( __METHOD__, $parameters['namespace'], '' ) )
+ ->newEmptySemanticData();
+
+ $instance = new CategoryPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $parameters['categories']
+ );
+
+ $instance->showHiddenCategories(
+ $parameters['settings']['showHiddenCategories']
+ );
+
+ $instance->useCategoryInstance(
+ $parameters['settings']['categoriesAsInstances']
+ );
+
+ $instance->useCategoryHierarchy(
+ $parameters['settings']['categoryHierarchy']
+ );
+
+ $instance->useCategoryRedirect(
+ false
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ /**
+ * @dataProvider categoriesDataProvider
+ */
+ public function testAddCategoriesWithParserDataUpdate( array $parameters, array $expected ) {
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( new DIWikiPage( __METHOD__, $parameters['namespace'], '' ) )
+ ->newEmptySemanticData();
+
+ $title = $semanticData->getSubject()->getTitle();
+ $parserOutput = new ParserOutput();
+ $parserData = new ParserData( $title, $parserOutput );
+
+ $instance = new CategoryPropertyAnnotator(
+ new NullPropertyAnnotator( $parserData->getSemanticData() ),
+ $parameters['categories']
+ );
+
+ $instance->showHiddenCategories(
+ $parameters['settings']['showHiddenCategories']
+ );
+
+ $instance->useCategoryInstance(
+ $parameters['settings']['categoriesAsInstances']
+ );
+
+ $instance->useCategoryHierarchy(
+ $parameters['settings']['categoryHierarchy']
+ );
+
+ $instance->useCategoryRedirect(
+ false
+ );
+
+ $instance->addAnnotation();
+ $parserData->pushSemanticDataToParserOutput();
+
+ $parserDataAfterAnnotation = new ParserData( $title, $parserOutput );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $parserDataAfterAnnotation->getSemanticData()
+ );
+ }
+
+ /**
+ * @dataProvider hiddenCategoriesDataProvider
+ */
+ public function testAddCategoriesWithHiddenCategories( array $parameters, array $expected ) {
+
+ $expectedPageLookup = $parameters['settings']['showHiddenCategories'] ? $this->never() : $this->atLeastOnce();
+
+ $wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $wikiPage->expects( $expectedPageLookup )
+ ->method( 'getHiddenCategories' )
+ ->will( $this->returnValue( $parameters['hidCategories'] ) );
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageCreator->expects( $expectedPageLookup )
+ ->method( 'createPage' )
+ ->will( $this->returnValue( $wikiPage ) );
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( new DIWikiPage( __METHOD__, $parameters['namespace'], '' ) )
+ ->newEmptySemanticData();
+
+ $this->testEnvironment->registerObject(
+ 'PageCreator',
+ $pageCreator
+ );
+
+ $instance = new CategoryPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $parameters['categories']
+ );
+
+ $instance->showHiddenCategories(
+ $parameters['settings']['showHiddenCategories']
+ );
+
+ $instance->useCategoryInstance(
+ $parameters['settings']['categoriesAsInstances']
+ );
+
+ $instance->useCategoryHierarchy(
+ $parameters['settings']['categoryHierarchy']
+ );
+
+ $instance->useCategoryRedirect(
+ false
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $semanticData
+ );
+ }
+
+ public function testAddCategoryOnInvalidRedirect() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnValue( new DIWikiPage( 'Foo', NS_MAIN ) ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( new DIWikiPage( __METHOD__, NS_MAIN ) )
+ ->newEmptySemanticData();
+
+ $instance = new CategoryPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ [ 'Bar' ]
+ );
+
+ $instance->useCategoryRedirect(
+ true
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_ERRC'
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function categoriesDataProvider() {
+
+ $provider = [];
+
+ // Standard category
+ $provider[] = [
+ [
+ 'namespace' => NS_MAIN,
+ 'categories' => [ 'Foo', 'Bar' ],
+ 'settings' => [
+ 'categoryHierarchy' => false,
+ 'categoriesAsInstances' => true,
+ 'showHiddenCategories' => true
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_INST',
+ 'propertyValues' => [ 'Foo', 'Bar' ],
+ ]
+ ];
+
+ // Category hierarchy or Sub-category
+ $provider[] = [
+ [
+ 'namespace' => NS_CATEGORY,
+ 'categories' => [ 'Foo', 'Bar' ],
+ 'settings' => [
+ 'categoryHierarchy' => true,
+ 'categoriesAsInstances' => false,
+ 'showHiddenCategories' => true
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_SUBC',
+ 'propertyValues' => [ 'Foo', 'Bar' ],
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function hiddenCategoriesDataProvider() {
+
+ $provider = [];
+
+ $hidCategory = MockTitle::buildMock( __METHOD__ );
+
+ $hidCategory->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_CATEGORY ) );
+
+ $hidCategory->expects( $this->any() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ // #0 Standard category, show hidden category
+ $provider[] = [
+ [
+ 'namespace' => NS_MAIN,
+ 'categories' => [ 'Foo', 'Bar' ],
+ 'hidCategories' => [ $hidCategory ],
+ 'settings' => [
+ 'categoryHierarchy' => false,
+ 'categoriesAsInstances' => true,
+ 'showHiddenCategories' => true
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_INST',
+ 'propertyValues' => [ 'Foo', 'Bar' ],
+ ]
+ ];
+
+ // #1 Standard category, omit hidden category
+ $provider[] = [
+ [
+ 'namespace' => NS_MAIN,
+ 'categories' => [ 'Foo', 'Bar' ],
+ 'hidCategories' => [ $hidCategory ],
+ 'settings' => [
+ 'categoryHierarchy' => false,
+ 'categoriesAsInstances' => true,
+ 'showHiddenCategories' => false
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_INST',
+ 'propertyValues' => [ 'Foo' ],
+ ]
+ ];
+
+ // #2 Category hierarchy or Sub-category, show hidden category
+ $provider[] = [
+ [
+ 'namespace' => NS_CATEGORY,
+ 'categories' => [ 'Foo', 'Bar' ],
+ 'hidCategories' => [ $hidCategory ],
+ 'settings' => [
+ 'categoryHierarchy' => true,
+ 'categoriesAsInstances' => false,
+ 'showHiddenCategories' => true
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_SUBC',
+ 'propertyValues' => [ 'Foo', 'Bar' ],
+ ]
+ ];
+
+ // #3 Category hierarchy or Sub-category, omit hidden category
+ $provider[] = [
+ [
+ 'namespace' => NS_CATEGORY,
+ 'categories' => [ 'Foo', 'Bar' ],
+ 'hidCategories' => [ $hidCategory ],
+ 'settings' => [
+ 'categoryHierarchy' => true,
+ 'categoriesAsInstances' => false,
+ 'showHiddenCategories' => false
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_SUBC',
+ 'propertyValues' => [ 'Foo' ],
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/ChainablePropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/ChainablePropertyAnnotatorTest.php
new file mode 100644
index 00000000..f5f3723d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/ChainablePropertyAnnotatorTest.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DIProperty;
+use SMW\PropertyAnnotators\CategoryPropertyAnnotator;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\PropertyAnnotators\PredefinedPropertyAnnotator;
+use SMW\PropertyAnnotators\SortKeyPropertyAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ChainablePropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ /**
+ * @dataProvider annotationDataProvider
+ */
+ public function testChainableDecoratorAnnotation( array $parameters, array $expected ) {
+
+ $pageInfoProvider = $this->getMockBuilder( '\SMW\PageInfo' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageInfoProvider->expects( $this->atLeastOnce() )
+ ->method( 'getModificationDate' )
+ ->will( $this->returnValue( $parameters['modificationDate'] ) );
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $categoryPropertyAnnotator = new CategoryPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $parameters['categories']
+ );
+
+ $categoryPropertyAnnotator->showHiddenCategories(
+ $parameters['settings']['showHiddenCategories']
+ );
+
+ $categoryPropertyAnnotator->useCategoryInstance(
+ $parameters['settings']['categoriesAsInstances']
+ );
+
+ $categoryPropertyAnnotator->useCategoryHierarchy(
+ $parameters['settings']['categoryHierarchy']
+ );
+
+ $categoryPropertyAnnotator->useCategoryRedirect(
+ false
+ );
+
+ $sortKeyPropertyAnnotator = new SortKeyPropertyAnnotator(
+ $categoryPropertyAnnotator,
+ $parameters['sortkey']
+ );
+
+ $predefinedPropertyAnnotator = new PredefinedPropertyAnnotator(
+ $sortKeyPropertyAnnotator,
+ $pageInfoProvider
+ );
+
+ $predefinedPropertyAnnotator->setPredefinedPropertyList(
+ $parameters['settings']['smwgPageSpecialProperties']
+ );
+
+ $predefinedPropertyAnnotator->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $predefinedPropertyAnnotator->getSemanticData()
+ );
+ }
+
+ public function annotationDataProvider() {
+
+ $provider = [];
+
+ // #0
+ $provider[] = [
+ [
+ 'modificationDate' => 1272508903,
+ 'categories' => [ 'Foo', 'Bar' ],
+ 'sortkey' => 'Lala',
+ 'settings' => [
+ 'categoryHierarchy' => false,
+ 'categoriesAsInstances' => true,
+ 'showHiddenCategories' => true,
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MODIFICATION_DATE ]
+ ]
+ ],
+ [
+ 'propertyCount' => 3,
+ 'propertyKeys' => [ '_INST', '_MDAT', '_SKEY' ],
+ 'propertyValues' => [ 'Foo', 'Bar', '2010-04-29T02:41:43', 'Lala' ],
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/DisplayTitlePropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/DisplayTitlePropertyAnnotatorTest.php
new file mode 100644
index 00000000..e2917a57
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/DisplayTitlePropertyAnnotatorTest.php
@@ -0,0 +1,236 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\PropertyAnnotators\DisplayTitlePropertyAnnotator;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\PropertyAnnotators\DisplayTitlePropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DisplayTitlePropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+
+ $this->semanticDataFactory = $testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+ $this->semanticDataValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DisplayTitlePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\DisplayTitlePropertyAnnotator',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider displayTitleProvider
+ */
+ public function testAddAnnotationForDisplayTitle( $title, $displayTitle, $defaultSort, array $expected ) {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ $title
+ );
+
+ $instance = new DisplayTitlePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $displayTitle,
+ $defaultSort
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testAddAnnotationForWhenPropertyNamespaceIsUsed() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY )
+ );
+
+ $instance = new DisplayTitlePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ 'Bar'
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_DTITLE', '_SKEY' ],
+ 'propertyValues' => [ 'Bar' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testNoAnnotationWhenDisabled() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ DIWikiPage::newFromText( 'Foo' )
+ );
+
+ $instance = new DisplayTitlePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ 'Bar'
+ );
+ $instance->canCreateAnnotation( false );
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 0
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function displayTitleProvider() {
+
+ $provider = [];
+
+ #0 with title entry
+ $provider[] = [
+ 'Foo',
+ 'Lala',
+ '',
+ [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_DTITLE', '_SKEY' ],
+ 'propertyValues' => [ 'Lala' ],
+ ]
+ ];
+
+ #1 Empty
+ $provider[] = [
+ 'Bar',
+ '',
+ '',
+ [
+ 'propertyCount' => 0,
+ 'propertyKeys' => '',
+ 'propertyValues' => [],
+ ]
+ ];
+
+ #2 Empty
+ $provider[] = [
+ 'Bar',
+ false,
+ '',
+ [
+ 'propertyCount' => 0,
+ 'propertyKeys' => '',
+ 'propertyValues' => [],
+ ]
+ ];
+
+ #3 Strip tags
+ $provider[] = [
+ 'Bar',
+ '<span style="position: absolute; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px);">FOO</span>',
+ '',
+ [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_DTITLE', '_SKEY' ],
+ 'propertyValues' => [ 'FOO' ],
+ ]
+ ];
+
+
+ #4 Strip tags
+ $provider[] = [
+ 'Foo',
+ "A 'quote' is <b>bold</b>",
+ '',
+ [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_DTITLE', '_SKEY' ],
+ 'propertyValues' => [ "A 'quote' is bold" ],
+ ]
+ ];
+
+ #5 with different sortkey
+ $provider[] = [
+ 'Foo',
+ 'Lala',
+ 'BAR',
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_DTITLE' ],
+ 'propertyValues' => [ 'Lala' ],
+ ]
+ ];
+
+ #6 unencoded Html entity
+ $provider[] = [
+ 'Foo',
+ 'ABC & DEF',
+ '',
+ [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_DTITLE', '_SKEY' ],
+ 'propertyValues' => [ 'ABC & DEF' ],
+ ]
+ ];
+
+ #7 decoded/encoded Html entity
+ $provider[] = [
+ 'Foo',
+ 'ABC &amp; DEF',
+ '',
+ [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_DTITLE', '_SKEY' ],
+ 'propertyValues' => [ 'ABC & DEF' ],
+ ]
+ ];
+
+ #8 decoded/encoded ' (&#39;) entity
+ $provider[] = [
+ 'Foo',
+ 'ABC &#39; DEF',
+ '',
+ [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_DTITLE', '_SKEY' ],
+ 'propertyValues' => [ "ABC ' DEF" ],
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/EditProtectedPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/EditProtectedPropertyAnnotatorTest.php
new file mode 100644
index 00000000..4b33749b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/EditProtectedPropertyAnnotatorTest.php
@@ -0,0 +1,232 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DataItemFactory;
+use SMW\PropertyAnnotators\EditProtectedPropertyAnnotator;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\PropertyAnnotators\EditProtectedPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class EditProtectedPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->semanticDataFactory = $testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+ $this->semanticDataValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new EditProtectedPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $title
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\EditProtectedPropertyAnnotator',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testAddAnnotationForDisplayTitle( $title, $editProtectionRight, array $expected ) {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ $title
+ );
+
+ $instance = new EditProtectedPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $title
+ );
+
+ $instance->setEditProtectionRight( $editProtectionRight );
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testAddTopIndicatorToFromMatchableRestriction() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // FIXME 3.0; Only MW 1.25+ (ParserOutput::setIndicator)
+ if ( !method_exists( $parserOutput, 'setIndicator' ) ) {
+ return $this->markTestSkipped( 'Only MW 1.25+ (ParserOutput::setIndicator)' );
+ }
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'setIndicator' );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'isProtected' )
+ ->with( $this->equalTo( 'edit' ) )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->once() )
+ ->method( 'getRestrictions' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ $instance = new EditProtectedPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $title
+ );
+
+ $instance->setEditProtectionRight( 'Foo' );
+ $instance->addTopIndicatorTo( $parserOutput );
+ }
+
+ public function titleProvider() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( 0 ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isProtected' )
+ ->with( $this->equalTo( 'edit' ) )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getRestrictions' )
+ ->will( $this->returnValue( [] ) );
+
+ $provider = [];
+
+ #0 no EditProtectionRight
+ $provider[] = [
+ $title,
+ false,
+ [
+ 'propertyCount' => 0,
+ 'propertyKeys' => [],
+ 'propertyValues' => [],
+ ]
+ ];
+
+ #1
+ $provider[] = [
+ $title,
+ 'Foo',
+ [
+ 'propertyCount' => 0,
+ 'propertyKeys' => [],
+ 'propertyValues' => [],
+ ]
+ ];
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( 0 ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isProtected' )
+ ->with( $this->equalTo( 'edit' ) )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getRestrictions' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ #2
+ $provider[] = [
+ $title,
+ 'Foo',
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_EDIP' ],
+ 'propertyValues' => [ true ],
+ ]
+ ];
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( 0 ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isProtected' )
+ ->with( $this->equalTo( 'edit' ) )
+ ->will( $this->returnValue( false ) );
+
+ $title->expects( $this->never() )
+ ->method( 'getRestrictions' );
+
+ #3
+ $provider[] = [
+ $title,
+ 'Foo',
+ [
+ 'propertyCount' => 0,
+ 'propertyKeys' => [],
+ 'propertyValues' => [],
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/MandatoryTypePropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/MandatoryTypePropertyAnnotatorTest.php
new file mode 100644
index 00000000..81263d59
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/MandatoryTypePropertyAnnotatorTest.php
@@ -0,0 +1,234 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\PropertyAnnotators\MandatoryTypePropertyAnnotator;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+use SMWDIUri as DIUri;
+
+/**
+ * @covers \SMW\PropertyAnnotators\MandatoryTypePropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class MandatoryTypePropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new MandatoryTypePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\MandatoryTypePropertyAnnotator',
+ $instance
+ );
+ }
+
+ public function testNoImportForNoProperty() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->never() )
+ ->method( 'getPropertyValues' );
+
+ $instance = new MandatoryTypePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ $instance->addAnnotation();
+ }
+
+ public function testNoImportForPredefinedProperty() {
+
+ $subject = DIWikiPage::newFromText( 'Modification date', SMW_NS_PROPERTY );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->never() )
+ ->method( 'getPropertyValues' );
+
+ $instance = new MandatoryTypePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ $instance->addAnnotation();
+ }
+
+ public function testValidImportTypeReferenceToSetType() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY )
+ );
+
+ $importValue = DataValueFactory::getInstance()->newDataValueByItem(
+ new DIBlob( 'foo' . ' ' . 'bar' . ' ' . 'buz' . ' ' . 'Type:Text' ),
+ new DIProperty( '_IMPO' )
+ );
+
+ $semanticData->addDataValue( $importValue );
+
+ $instance = new MandatoryTypePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'properties' => [ new DIProperty( '_TYPE' ), new DIProperty( '_IMPO' ) ],
+ 'propertyValues' => [ 'Text', 'foo:bar' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testValidImportTypeReferenceToOverrideUserType() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY )
+ );
+
+ $importValue = DataValueFactory::getInstance()->newDataValueByItem(
+ new DIBlob( 'foo' . ' ' . 'bar' . ' ' . 'buz' . ' ' . 'Type:Page' ),
+ new DIProperty( '_IMPO' )
+ );
+
+ $semanticData->addDataValue( $importValue );
+
+ $typeValue = DataValueFactory::getInstance()->newDataValueByItem(
+ new DIUri( 'http', 'semantic-mediawiki.org/swivt/1.0', '', '_txt' ),
+ new DIProperty( '_TYPE' )
+ );
+
+ $semanticData->addDataValue( $typeValue );
+
+ $instance = new MandatoryTypePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ // Check before
+ $expected = [
+ 'properties' => [ new DIProperty( '_TYPE' ), new DIProperty( '_IMPO' ) ],
+ 'propertyValues' => [ 'Text', 'foo:bar' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+
+ $instance->addAnnotation();
+
+ // Check after
+ $expected = [
+ 'properties' => [ new DIProperty( '_TYPE' ), new DIProperty( '_IMPO' ) ],
+ 'propertyValues' => [ 'Page', 'foo:bar' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testInvalidImportTypeReferenceDoesNotSetAnyType() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY )
+ );
+
+ $importValue = DataValueFactory::getInstance()->newDataValueByItem(
+ new DIBlob( 'foo' . ' ' . 'bar' . ' ' . 'buz' . ' ' . 'Type-Text' ),
+ new DIProperty( '_IMPO' )
+ );
+
+ $semanticData->addDataValue( $importValue );
+
+ $instance = new MandatoryTypePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'properties' => [ new DIProperty( '_IMPO' ) ],
+ 'propertyValues' => [ 'foo:bar' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testBogusImportTypeDoesNotSetAnyType() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData(
+ DIWikiPage::newFromText( __METHOD__, SMW_NS_PROPERTY )
+ );
+
+ $importValue = DataValueFactory::getInstance()->newDataValueByItem(
+ new DIBlob( 'foo' . ' ' . 'bar' . ' ' . 'buz' . ' ' . 'Type:Bogus' ),
+ new DIProperty( '_IMPO' )
+ );
+
+ $semanticData->addDataValue( $importValue );
+
+ $instance = new MandatoryTypePropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData )
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'properties' => [ new DIProperty( '_IMPO' ) ],
+ 'propertyValues' => [ 'foo:bar' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/NullPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/NullPropertyAnnotatorTest.php
new file mode 100644
index 00000000..ff2b5e5c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/NullPropertyAnnotatorTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+
+/**
+ * @covers \SMW\PropertyAnnotators\NullPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class NullPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\NullPropertyAnnotator',
+ new NullPropertyAnnotator( $semanticData )
+ );
+ }
+
+ public function testMethodAccess() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new NullPropertyAnnotator( $semanticData );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $instance->getSemanticData()
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\NullPropertyAnnotator',
+ $instance->addAnnotation()
+ );
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/PredefinedPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/PredefinedPropertyAnnotatorTest.php
new file mode 100644
index 00000000..2d70ee9e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/PredefinedPropertyAnnotatorTest.php
@@ -0,0 +1,366 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\PropertyAnnotators\PredefinedPropertyAnnotator;
+use SMW\Tests\Utils\Mock\MockTitle;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @covers \SMW\PropertyAnnotators\PredefinedPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class PredefinedPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $pageInfo = $this->getMockBuilder( '\SMW\PageInfo' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PredefinedPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $pageInfo
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\PredefinedPropertyAnnotator',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider specialPropertiesDataProvider
+ */
+ public function testAddSpecialProperties( array $parameters, array $expected ) {
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( $parameters['subject'] )
+ ->newEmptySemanticData();
+
+ $pageInfo = $this->getMockBuilder( '\SMW\PageInfo' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $parameters['pageInfo'] as $method => $returnValue ) {
+ $pageInfo->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->returnValue( $returnValue ) );
+ }
+
+ $instance = new PredefinedPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $pageInfo
+ );
+
+ $instance->setPredefinedPropertyList(
+ $parameters['settings']['smwgPageSpecialProperties']
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function specialPropertiesDataProvider() {
+
+ $provider = [];
+
+ #0 Unknown
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'UNKNOWN' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ 'Lala', '_Lula', '-Lila', '' ]
+ ],
+ 'pageInfo' => [],
+ ],
+ [
+ 'propertyCount' => 0,
+ ]
+ ];
+
+ #1 TYPE_MODIFICATION_DATE
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'withModificationDate' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MODIFICATION_DATE ]
+ ],
+ 'pageInfo' => [ 'getModificationDate' => 1272508903 ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_MDAT',
+ 'propertyValues' => [ '2010-04-29T02:41:43' ],
+ ]
+ ];
+
+ #2 TYPE_CREATION_DATE
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'withCreationDate' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_CREATION_DATE ]
+ ],
+ 'pageInfo' => [ 'getCreationDate' => 1272508903 ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_CDAT',
+ 'propertyValues' => [ '2010-04-29T02:41:43' ],
+ ]
+ ];
+
+ #3 TYPE_NEW_PAGE
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'NEW_PAGE_isNew' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_NEW_PAGE ]
+ ],
+ 'pageInfo' => [ 'isNewPage' => true ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_NEWP',
+ 'propertyValues' => [ true ],
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'NEW_PAGE_isNotNew' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_NEW_PAGE ]
+ ],
+ 'pageInfo' => [ 'isNewPage' => false ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_NEWP',
+ 'propertyValues' => [ false ],
+ ]
+ ];
+
+ #5 TYPE_LAST_EDITOR
+ $userPage = MockTitle::buildMock( 'Lula' );
+ $userNS = Localizer::getInstance()->getNamespaceTextById( NS_USER );
+
+ $userPage->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_USER ) );
+
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'withLastEditor' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_LAST_EDITOR ]
+ ],
+ 'pageInfo' => [ 'getLastEditor' => $userPage ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_LEDT',
+ 'propertyValues' => [ ":$userNS:Lula" ],
+ ]
+ ];
+
+ #6 Combined entries
+ $userPage = MockTitle::buildMock( 'Lula' );
+ $userNS = Localizer::getInstance()->getNamespaceTextById( NS_USER );
+
+ $userPage->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_USER ) );
+
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'withCombinedEntries' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ '_MDAT', '_LEDT' ]
+ ],
+ 'pageInfo' => [
+ 'getModificationDate' => 1272508903,
+ 'getLastEditor' => $userPage
+ ]
+ ],
+ [
+ 'propertyCount' => 2,
+ 'propertyKeys' => [ '_MDAT', '_LEDT' ],
+ 'propertyValues' => [ '2010-04-29T02:41:43', ":$userNS:Lula" ],
+ ]
+ ];
+
+ #7 TYPE_MEDIA
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'MimePropertyForFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MEDIA ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => true,
+ 'getMediaType' => 'FooMedia'
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_MEDIA',
+ 'propertyValues' => [ 'FooMedia' ],
+ ]
+ ];
+
+ #8
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'MediaPropertyForNonFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MEDIA ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => false,
+ 'getMediaType' => 'FooMedia'
+ ]
+ ],
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ #9 TYPE_MIME
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'MimePropertyForFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MIME ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => true,
+ 'getMimeType' => 'FooMime'
+ ]
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_MIME',
+ 'propertyValues' => [ 'FooMime' ],
+ ]
+ ];
+
+ #10
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'MimePropertyForNonFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MIME ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => false,
+ 'getMimeType' => 'FooMime'
+ ]
+ ],
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ #11 Empty TYPE_MIME
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'EmptyMimePropertyFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MIME ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => true,
+ 'getMimeType' => ''
+ ]
+ ],
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ #12 Empty TYPE_MEDIA
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'EmptyMediaPropertyFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MEDIA ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => true,
+ 'getMediaType' => ''
+ ]
+ ],
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ #13 Null TYPE_MIME
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'NullMimePropertyFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MIME ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => true,
+ 'getMimeType' => null
+ ]
+ ],
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ #14 Null TYPE_MEDIA
+ $provider[] = [
+ [
+ 'subject' => DIWikiPage::newFromTitle( Title::newFromText( 'NullMediaPropertyFilePage' ) ),
+ 'settings' => [
+ 'smwgPageSpecialProperties' => [ DIProperty::TYPE_MEDIA ]
+ ],
+ 'pageInfo' => [
+ 'isFilePage' => true,
+ 'getMimeType' => null
+ ]
+ ],
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/RedirectPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/RedirectPropertyAnnotatorTest.php
new file mode 100644
index 00000000..73b8b8cc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/RedirectPropertyAnnotatorTest.php
@@ -0,0 +1,116 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\MediaWiki\RedirectTargetFinder;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\PropertyAnnotators\RedirectPropertyAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\PropertyAnnotators\RedirectPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class RedirectPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $redirectTargetFinder = $this->getMockBuilder( '\SMW\MediaWiki\RedirectTargetFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new RedirectPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $redirectTargetFinder
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\RedirectPropertyAnnotator',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider redirectsDataProvider
+ */
+ public function testAddAnnotation( array $parameter, array $expected ) {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $redirectTargetFinder = new RedirectTargetFinder();
+
+ $instance = new RedirectPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $redirectTargetFinder->findRedirectTargetFromText( $parameter['text'] )
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function redirectsDataProvider() {
+
+ // #0 Free text
+ $provider[] = [
+ [ 'text' => '#REDIRECT [[:Lala]]' ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_REDI',
+ 'propertyValues' => ':Lala'
+ ]
+ ];
+
+ // #1 Free text
+ $provider[] = [
+ [ 'text' => '#REDIRECT [[Lala]]' ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_REDI',
+ 'propertyValues' => ':Lala'
+ ]
+ ];
+
+
+ // #2 Invalid free text
+ $provider[] = [
+ [ 'text' => '#REDIR [[:Lala]]' ],
+ [
+ 'propertyCount' => 0,
+ ]
+ ];
+
+ // #3 Empty
+ $provider[] = [
+ [ 'text' => '' ],
+ [
+ 'propertyCount' => 0,
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SchemaPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SchemaPropertyAnnotatorTest.php
new file mode 100644
index 00000000..d2b23d1c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SchemaPropertyAnnotatorTest.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DataItemFactory;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\PropertyAnnotators\SchemaPropertyAnnotator;
+use SMW\Schema\SchemaDefinition;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\PropertyAnnotators\SchemaPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SchemaPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+ $this->semanticDataFactory = $testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+ $this->semanticDataValidator = $testEnvironment->newValidatorFactory()->newSemanticDataValidator();
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SchemaPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ new SchemaDefinition( 'foo', [] )
+ );
+
+ $this->assertInstanceOf(
+ SchemaPropertyAnnotator::class,
+ $instance
+ );
+ }
+
+ public function testAddAnnotation() {
+
+ $def = [
+ SchemaDefinition::SCHEMA_TYPE => 'bar',
+ SchemaDefinition::SCHEMA_DESCRIPTION => '...',
+ SchemaDefinition::SCHEMA_TAG => [ 'foobar' ],
+ ];
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $instance = new SchemaPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ new SchemaDefinition( 'foo', $def )
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 4,
+ 'propertyKeys' => [ '_SCHEMA_TYPE', '_SCHEMA_DEF', '_SCHEMA_DESC', '_SCHEMA_TAG' ],
+ 'propertyValues' => [ 'bar', '...', 'foobar', '{"type":"bar","description":"...","tags":["foobar"]}' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SortKeyPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SortKeyPropertyAnnotatorTest.php
new file mode 100644
index 00000000..abc4095e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/SortKeyPropertyAnnotatorTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DataItemFactory;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\PropertyAnnotators\SortKeyPropertyAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\PropertyAnnotators\SortKeyPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SortKeyPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $semanticDataValidator;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SortKeyPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ 'Foo'
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyAnnotators\SortKeyPropertyAnnotator',
+ $instance
+ );
+ }
+
+ /**
+ * @dataProvider defaultSortDataProvider
+ */
+ public function testAddAnnotation( array $parameters, array $expected ) {
+
+ $semanticData = $this->semanticDataFactory->setTitle( $parameters['title'] )->newEmptySemanticData();
+
+ $instance = new SortKeyPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $parameters['sort']
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testDontOverrideAnnotationIfAlreadyAvailable() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $semanticData->addPropertyObjectValue(
+ $this->dataItemFactory->newDIProperty( '_SKEY' ),
+ $this->dataItemFactory->newDIBlob( 'FOO' )
+ );
+
+ $instance = new SortKeyPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ 'bar'
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_SKEY',
+ 'propertyValues' => [ 'FOO' ],
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function defaultSortDataProvider() {
+
+ $provider = [];
+
+ // Sort entry
+ $provider[] = [
+ [
+ 'title' => 'Foo',
+ 'sort' => 'Lala'
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_SKEY',
+ 'propertyValues' => [ 'Lala' ],
+ ]
+ ];
+
+ // Empty
+ $provider[] = [
+ [
+ 'title' => 'Bar',
+ 'sort' => ''
+ ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_SKEY',
+ 'propertyValues' => [ 'Bar' ],
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/TranslationPropertyAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/TranslationPropertyAnnotatorTest.php
new file mode 100644
index 00000000..154f6653
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyAnnotators/TranslationPropertyAnnotatorTest.php
@@ -0,0 +1,160 @@
+<?php
+
+namespace SMW\Tests\PropertyAnnotators;
+
+use SMW\DataItemFactory;
+use SMW\SemanticData;
+use SMW\PropertyAnnotators\NullPropertyAnnotator;
+use SMW\PropertyAnnotators\TranslationPropertyAnnotator;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\PropertyAnnotators\TranslationPropertyAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TranslationPropertyAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = TestEnvironment::newValidatorFactory()->newSemanticDataValidator();
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new TranslationPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ []
+ );
+
+ $this->assertInstanceOf(
+ TranslationPropertyAnnotator::class,
+ $instance
+ );
+ }
+
+ public function testAddAnnotation() {
+
+ $semanticData = new SemanticData(
+ $this->dataItemFactory->newDIWikiPage( 'Foo' )
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foobar' ) );
+
+ $title->expects( $this->once() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $translation = [
+ 'languagecode' => 'foo',
+ 'sourcepagetitle' => $title,
+ 'messagegroupid' => 'bar'
+ ];
+
+ $expected = [
+ 'propertyCount' => 3,
+ 'propertyKeys' => [ '_LCODE', '_TRANS_GROUP', '_TRANS_SOURCE' ],
+ 'propertyValues' => [ 'foo', 'bar', ':Foobar' ],
+ ];
+
+ $instance = new TranslationPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $translation
+ );
+
+ $instance->setPredefinedPropertyList( [ '_TRANS' ] );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => '_TRANS'
+ ],
+ $instance->getSemanticData()
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()->findSubSemanticData( 'trans.foo' )
+ );
+ }
+
+ public function testAddAnnotation_NotListed() {
+
+ $semanticData = new SemanticData(
+ $this->dataItemFactory->newDIWikiPage( 'Foo' )
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->never() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foobar' ) );
+
+ $title->expects( $this->never() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $translation = [
+ 'languagecode' => 'foo',
+ 'sourcepagetitle' => $title,
+ 'messagegroupid' => 'bar'
+ ];
+
+ $instance = new TranslationPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $translation
+ );
+
+ $instance->setPredefinedPropertyList( [] );
+ $instance->addAnnotation();
+ }
+
+ public function testAddAnnotation_EmptyData() {
+
+ $semanticData = new SemanticData(
+ $this->dataItemFactory->newDIWikiPage( 'Foo' )
+ );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $translation = [];
+
+ $instance = new TranslationPropertyAnnotator(
+ new NullPropertyAnnotator( $semanticData ),
+ $translation
+ );
+
+ $instance->addAnnotation();
+
+ $this->assertEquals(
+ $semanticData,
+ $instance->getSemanticData()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyChangePropagationNotifierTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyChangePropagationNotifierTest.php
new file mode 100644
index 00000000..5955bd87
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyChangePropagationNotifierTest.php
@@ -0,0 +1,209 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\PropertyChangePropagationNotifier;
+
+/**
+ * @covers \SMW\PropertyChangePropagationNotifier
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class PropertyChangePropagationNotifierTest extends \PHPUnit_Framework_TestCase {
+
+ protected $mockedStoreValues;
+ private $semanticData;
+ private $serializerFactory;
+ private $store;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment(
+ [
+ 'smwgChangePropagationWatchlist' => [ '_PVAL' ],
+ 'smwgMainCacheType' => 'hash',
+ 'smwgEnableUpdateJobs' => false
+ ]
+ );
+
+ $semanticDataSerializer = $this->getMockBuilder( '\SMW\Serializers\SemanticDataSerializer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->serializerFactory = $this->getMockBuilder( '\SMW\SerializerFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->serializerFactory->expects( $this->any() )
+ ->method( 'newSemanticDataSerializer' )
+ ->will( $this->returnValue( $semanticDataSerializer ) );
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertyChangePropagationNotifier::class,
+ new PropertyChangePropagationNotifier( $this->store, $this->serializerFactory )
+ );
+ }
+
+ /**
+ * @dataProvider dataItemDataProvider
+ */
+ public function testDetectChangesOnProperty( $mockedStoreValues, $dataValues, $propertiesToCompare, $expected ) {
+
+ if ( !method_exists( 'JobQueueGroup', 'lazyPush' ) ) {
+ $this->markTestSkipped( 'JobQueueGroup::lazyPush is not supported.' );
+ }
+
+ $subject = new DIWikiPage( __METHOD__, SMW_NS_PROPERTY );
+
+ $this->detectChanges(
+ $subject,
+ $mockedStoreValues,
+ $dataValues,
+ $propertiesToCompare,
+ $expected
+ );
+ }
+
+ /**
+ * @dataProvider dataItemDataProvider
+ */
+ public function testDetectChangesOnCategory( $mockedStoreValues, $dataValues, $propertiesToCompare, $expected ) {
+
+ if ( !method_exists( 'JobQueueGroup', 'lazyPush' ) ) {
+ $this->markTestSkipped( 'JobQueueGroup::lazyPush is not supported.' );
+ }
+
+ $subject = new DIWikiPage( __METHOD__, NS_CATEGORY );
+
+ $this->detectChanges(
+ $subject,
+ $mockedStoreValues,
+ $dataValues,
+ $propertiesToCompare,
+ $expected
+ );
+ }
+
+ public function detectChanges( $subject, $mockedStoreValues, $dataValues, $propertiesToCompare, $expected ) {
+
+ $this->mockedStoreValues = $mockedStoreValues;
+
+ $expectedToRun = $expected['job'] ? $this->atLeastOnce() : $this->never();
+
+ $jobQueueGroup = $this->getMockBuilder( '\JobQueueGroup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueueGroup->expects( $expectedToRun )
+ ->method( 'lazyPush' );
+
+ $this->testEnvironment->registerObject( 'JobQueueGroup', $jobQueueGroup );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( 'SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyValues', 'getSemanticData' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnCallback( [ $this, 'doComparePropertyValuesOnCallback' ] ) );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( $dataValues ) );
+
+ $instance = new PropertyChangePropagationNotifier(
+ $store,
+ $this->serializerFactory
+ );
+
+ $instance->setPropertyList( $propertiesToCompare );
+
+ $instance->checkAndNotify( $semanticData );
+
+ $this->assertEquals(
+ $expected['diff'],
+ $instance->hasDiff()
+ );
+ }
+
+ public function dataItemDataProvider() {
+
+ // Single
+ $subject = [
+ DIWikiPage::newFromText( __METHOD__ )
+ ];
+
+ // Multiple
+ $subjects = [
+ DIWikiPage::newFromText( __METHOD__ . 'm-0' ),
+ DIWikiPage::newFromText( __METHOD__ . 'm-1' ),
+ DIWikiPage::newFromText( __METHOD__ . 'm-2' )
+ ];
+
+ return [
+ // $mockedStoreValues, $dataValues, $settings, $expected
+ [ $subjects, [], [ '_PVAL', '_LIST' ], [ 'diff' => true, 'job' => true ] ],
+ [ [], $subjects, [ '_PVAL', '_LIST' ], [ 'diff' => true, 'job' => true ] ],
+ [ $subject, $subjects, [ '_PVAL', '_LIST' ], [ 'diff' => true, 'job' => true ] ],
+ [ $subject, [], [ '_PVAL', '_LIST' ], [ 'diff' => true, 'job' => true ] ],
+ [ $subject, [], [ '_PVAL' ], [ 'diff' => true, 'job' => true ] ],
+ [ $subjects, $subjects, [ '_PVAL' ], [ 'diff' => false, 'job' => false ] ],
+ [ $subject, $subject, [ '_PVAL' ], [ 'diff' => false, 'job' => false ] ],
+ [ $subjects, $subjects, [ '_PVAL', '_LIST' ], [ 'diff' => true, 'job' => true ] ],
+ [ $subject, $subject, [ '_PVAL', '_LIST' ], [ 'diff' => true, 'job' => true ] ]
+ ];
+ }
+
+ /**
+ * Returns an array of SMWDataItem and simulates an alternating
+ * existencance of return values ('_LIST')
+ *
+ * @see Store::getPropertyValues
+ *
+ * @return SMWDataItem[]
+ */
+ // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.CodeAnalysis.UnusedFunctionParameter
+ public function doComparePropertyValuesOnCallback( $subject, DIProperty $property, $requestoptions = null ) { // @codingStandardsIgnoreEnd
+ return $property->getKey() === '_LIST' ? [] : $this->mockedStoreValues;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyLabelFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyLabelFinderTest.php
new file mode 100644
index 00000000..9f03aa90
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyLabelFinderTest.php
@@ -0,0 +1,206 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\PropertyLabelFinder;
+
+/**
+ * @covers \SMW\PropertyLabelFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PropertyLabelFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $testEnvironment;
+ private $propertySpecificationLookup;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ public function testCanConstruct() {
+
+ $languageIndependentPropertyLabels = [];
+ $canonicalPropertyLabels = [];
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyLabelFinder',
+ new PropertyLabelFinder( $this->store, $languageIndependentPropertyLabels, $canonicalPropertyLabels )
+ );
+ }
+
+ public function testPreLoadedPropertyLabel() {
+
+ $languageIndependentPropertyLabels = [ '_Foo' => 'Bar' ];
+ $canonicalPropertyLabels = [];
+
+ $instance = new PropertyLabelFinder(
+ $this->store,
+ $languageIndependentPropertyLabels,
+ $canonicalPropertyLabels
+ );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->findPropertyLabelById( '_Foo' )
+ );
+
+ $this->assertEquals(
+ '_Foo',
+ $instance->searchPropertyIdByLabel( 'Bar' )
+ );
+ }
+
+ public function testRegisterPropertyLabel() {
+
+ $languageIndependentPropertyLabels = [];
+ $canonicalPropertyLabels = [];
+
+ $instance = new PropertyLabelFinder(
+ $this->store,
+ $languageIndependentPropertyLabels,
+ $canonicalPropertyLabels
+ );
+
+ $instance->registerPropertyLabel(
+ '_Foo',
+ 'Bar'
+ );
+
+ $this->assertEquals(
+ [ '_Foo' => 'Bar' ],
+ $instance->getKownPredefinedPropertyLabels()
+ );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->findPropertyLabelById( '_Foo' )
+ );
+
+ $this->assertEquals(
+ '_Foo',
+ $instance->searchPropertyIdByLabel( 'Bar' )
+ );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->findCanonicalPropertyLabelById( '_Foo' )
+ );
+ }
+
+ public function testPreventKnownPropertyLabelToBeRegisteredAsCanonicalWithDifferentId() {
+
+ $languageIndependentPropertyLabels = [];
+
+ $canonicalPropertyLabels = [
+ 'Foo' => '_foo'
+ ];
+
+ $instance = new PropertyLabelFinder(
+ $this->store,
+ $languageIndependentPropertyLabels,
+ $canonicalPropertyLabels
+ );
+
+ $instance->registerPropertyLabel(
+ '_bar',
+ 'Foo',
+ true
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->findCanonicalPropertyLabelById( '_foo' )
+ );
+ }
+
+ public function testSearchPropertyIdForNonRegisteredLabel() {
+
+ $languageIndependentPropertyLabels = [];
+ $canonicalPropertyLabels = [];
+
+ $instance = new PropertyLabelFinder(
+ $this->store,
+ $languageIndependentPropertyLabels,
+ $canonicalPropertyLabels
+ );
+
+ $this->assertFalse(
+ $instance->searchPropertyIdByLabel( 'Bar' )
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->findPropertyLabelById( '_Foo' )
+ );
+ }
+
+ public function testFindPropertyLabelByLanguageCode() {
+
+ $languageIndependentPropertyLabels = [];
+ $canonicalPropertyLabels = [];
+
+ $instance = new PropertyLabelFinder(
+ $this->store,
+ $languageIndependentPropertyLabels,
+ $canonicalPropertyLabels
+ );
+
+ $this->assertEquals(
+ 'Booléen',
+ $instance->findPropertyLabelFromIdByLanguageCode( '_boo', 'fr' )
+ );
+
+ $this->assertEquals(
+ 'Boolean',
+ $instance->findPropertyLabelFromIdByLanguageCode( '_boo', 'en' )
+ );
+ }
+
+ public function testFindPropertyListFromLabelByLanguageCode() {
+
+ $instance = new PropertyLabelFinder(
+ $this->store
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->findPropertyListFromLabelByLanguageCode( '~*unknownProp*', 'ja' )
+ );
+ }
+
+ public function testFindPreferredPropertyLabelByLanguageCode() {
+
+ $this->propertySpecificationLookup->expects( $this->once() )
+ ->method( 'getPreferredPropertyLabelBy' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnValue( 'ABC' ) );
+
+ $instance = new PropertyLabelFinder(
+ $this->store
+ );
+
+ $this->assertEquals(
+ 'ABC',
+ $instance->findPreferredPropertyLabelByLanguageCode( 'Foo', 'fr' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRegistryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRegistryTest.php
new file mode 100644
index 00000000..714bbb42
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRegistryTest.php
@@ -0,0 +1,572 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataTypeRegistry;
+use SMW\DIProperty;
+use SMW\PropertyAliasFinder;
+use SMW\PropertyLabelFinder;
+use SMW\PropertyRegistry;
+
+/**
+ * @covers \SMW\PropertyRegistry
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PropertyRegistryTest extends \PHPUnit_Framework_TestCase {
+
+ private $cache;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ PropertyRegistry::clear();
+ DataTypeRegistry::clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $propertyLabelFinder = $this->getMockBuilder( '\SMW\PropertyLabelFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyAliasFinder = $this->getMockBuilder( '\SMW\PropertyAliasFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\PropertyRegistry',
+ new PropertyRegistry( $datatypeRegistry, $propertyLabelFinder, $propertyAliasFinder )
+ );
+ }
+
+ public function testGetInstance() {
+
+ $instance = PropertyRegistry::getInstance();
+
+ $this->assertSame(
+ $instance,
+ PropertyRegistry::getInstance()
+ );
+
+ PropertyRegistry::clear();
+
+ $this->assertNotSame(
+ $instance,
+ PropertyRegistry::getInstance()
+ );
+ }
+
+ public function testLanguageIndependantPropertyLabelAliasInvocation() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [ '_uri' => 'URL' ] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [ 'URI' => '_uri' ] ) );
+
+ $propertyLabelFinder = $this->getMockBuilder( '\SMW\PropertyLabelFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache,
+ [ 'Has type' => '_TYPE' ]
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $this->assertEquals(
+ [
+ 'Has type' => '_TYPE',
+ 'URI' => '_uri' ],
+ $instance->getKnownPropertyAliases()
+ );
+ }
+
+ public function testRegisterProperty() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $propertyLabelFinder = $this->getMockBuilder( '\SMW\PropertyLabelFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $instance->registerProperty(
+ DIProperty::TYPE_HAS_TYPE,
+ '__typ',
+ 'Has type',
+ true
+ );
+
+ $this->assertEquals(
+ [ '_TYPE' => [ '__typ', true, true ] ],
+ $instance->getPropertyList()
+ );
+
+ $this->assertTrue(
+ $instance->isVisible( '_TYPE' )
+ );
+
+ $this->assertTrue(
+ $instance->isAnnotable( '_TYPE' )
+ );
+
+ $this->assertTrue(
+ $instance->isRegistered( '_TYPE' )
+ );
+ }
+
+ public function testUnregisterProperty() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $propertyLabelFinder = $this->getMockBuilder( '\SMW\PropertyLabelFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $this->assertFalse(
+ $instance->isVisible( '_UnregisteredType' )
+ );
+
+ $this->assertFalse(
+ $instance->isAnnotable( '_UnregisteredType' )
+ );
+
+ $this->assertFalse(
+ $instance->isRegistered( '_UnregisteredType' )
+ );
+ }
+
+ public function testFindPropertyId() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyLabelFinder = new PropertyLabelFinder( $store, [] );
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $instance->registerProperty(
+ DIProperty::TYPE_HAS_TYPE,
+ '__typ',
+ 'Has type',
+ true
+ );
+
+ $instance->registerPropertyAlias( '_TYPE', 'foo' );
+
+ $this->assertEquals(
+ '_TYPE',
+ $instance->findPropertyIdByLabel( 'Has type' )
+ );
+
+ $this->assertEquals(
+ '_TYPE',
+ $instance->findPropertyIdByLabel( 'foo', true )
+ );
+
+ // findPropertyId legacy test
+ $this->assertEquals(
+ '_TYPE',
+ $instance->findPropertyId( 'Has type' )
+ );
+ }
+
+ public function testFindPropertyLabelForRegisteredId() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyLabelFinder = new PropertyLabelFinder( $store, [] );
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $instance->registerProperty(
+ DIProperty::TYPE_HAS_TYPE,
+ '__typ',
+ 'Has type',
+ true
+ );
+
+ $this->assertEquals(
+ 'Has type',
+ $instance->findPropertyLabelById( '_TYPE' )
+ );
+
+ // findPropertyLabel legacy test
+ $this->assertEquals(
+ 'Has type',
+ $instance->findPropertyLabel( '_TYPE' )
+ );
+
+ // This was part of an extra test but the extra test caused an segfault on postgres travis-ci
+
+ $this->assertEquals(
+ '__typ',
+ $instance->getPropertyTypeId( '_TYPE' )
+ );
+
+ // getPredefinedPropertyTypeId legacy test
+ $this->assertEquals(
+ '__typ',
+ $instance->getPredefinedPropertyTypeId( '_TYPE' )
+ );
+ }
+
+ public function testFindPropertyInfoForUnregisteredId() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyLabelFinder = new PropertyLabelFinder( $store, [] );
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->findPropertyLabelById( '_UnknownId' )
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->getPropertyTypeId( '_UnknownId' )
+ );
+
+ $this->assertFalse(
+ $instance->findPropertyIdByLabel( 'unknownLabel' )
+ );
+
+ $this->assertFalse(
+ $instance->findPropertyIdByLabel( 'unknownLabel', true )
+ );
+ }
+
+ public function testfindPropertyIdFromLabelByLanguageCode() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyLabelFinder = new PropertyLabelFinder( $store, [] );
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $this->assertEquals(
+ '_TYPE',
+ $instance->findPropertyIdFromLabelByLanguageCode( 'A le type', 'fr' )
+ );
+ }
+
+ public function testFindPropertyLabelByLanguageCode() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyLabelFinder = new PropertyLabelFinder( $store, [] );
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $this->assertEquals(
+ 'A le type',
+ $instance->findPropertyLabelFromIdByLanguageCode( '_TYPE', 'fr' )
+ );
+ }
+
+ public function testPropertyDescriptionMsgKey() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyLabelFinder = new PropertyLabelFinder( $store, [] );
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases
+ );
+
+ $instance->registerPropertyDescriptionMsgKeyById( '_foo', 'bar' );
+
+ $this->assertEquals(
+ 'bar',
+ $instance->findPropertyDescriptionMsgKeyById( '_foo' )
+ );
+
+ $this->assertEmpty(
+ $instance->findPropertyDescriptionMsgKeyById( 'unknown' )
+ );
+ }
+
+ public function testDataTypePropertyExemptionList() {
+
+ $datatypeRegistry = $this->getMockBuilder( '\SMW\DataTypeRegistry' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeLabels' )
+ ->will( $this->returnValue( [ '_foo' => 'Foo', '_foobar' => 'Foobar' ] ) );
+
+ $datatypeRegistry->expects( $this->once() )
+ ->method( 'getKnownTypeAliases' )
+ ->will( $this->returnValue( [ 'Bar' => '_bar' ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $propertyLabelFinder = new PropertyLabelFinder( $store, [] );
+
+ $propertyAliases = new PropertyAliasFinder(
+ $this->cache
+ );
+
+ $dataTypePropertyExemptionList = [ 'Foo', 'Bar' ];
+
+ $instance = new PropertyRegistry(
+ $datatypeRegistry,
+ $propertyLabelFinder,
+ $propertyAliases,
+ $dataTypePropertyExemptionList
+ );
+
+ $this->assertEquals(
+ '_foobar',
+ $instance->findPropertyIdByLabel( 'Foobar' )
+ );
+
+ $this->assertFalse(
+ $instance->findPropertyIdByLabel( 'Foo' )
+ );
+
+ $this->assertFalse(
+ $instance->findPropertyIdByLabel( 'Bar' )
+ );
+ }
+
+ /**
+ * @dataProvider typeToCanonicalLabelProvider
+ */
+ public function testFindCanonicalPropertyLabelById( $id, $expected ) {
+
+ $instance = PropertyRegistry::getInstance();
+
+ $this->assertSame(
+ $expected,
+ $instance->findCanonicalPropertyLabelById( $id )
+ );
+ }
+
+ public function typeToCanonicalLabelProvider() {
+
+ $provider[] = [
+ '_txt',
+ 'Text'
+ ];
+
+ $provider[] = [
+ '_TEXT',
+ 'Text'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRestrictionExaminerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRestrictionExaminerTest.php
new file mode 100644
index 00000000..35983b4c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertyRestrictionExaminerTest.php
@@ -0,0 +1,148 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\PropertyRestrictionExaminer;
+
+/**
+ * @covers \SMW\PropertyRestrictionExaminer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PropertyRestrictionExaminerTest extends \PHPUnit_Framework_TestCase {
+
+ private $user;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertyRestrictionExaminer::class,
+ new PropertyRestrictionExaminer()
+ );
+ }
+
+ public function testGrepPropertyFromRestrictionErrorMsg() {
+
+ $msg = '[2,"smw-datavalue-property-create-restriction","Has unknown","foo"]';
+
+ $this->assertInstanceOf(
+ DIProperty::class,
+ PropertyRestrictionExaminer::grepPropertyFromRestrictionErrorMsg( $msg )
+ );
+ }
+
+ public function testRestrictionForPredefinedProperty() {
+
+ $instance = new PropertyRestrictionExaminer();
+
+ $instance->checkRestriction( new DIProperty( '_MDAT' ) );
+
+ $this->assertTrue(
+ $instance->hasRestriction()
+ );
+ }
+
+ public function testRestrictionForPredefinedPropertyOnQueryContext() {
+
+ $instance = new PropertyRestrictionExaminer();
+ $instance->isQueryContext( true );
+
+ $instance->checkRestriction( new DIProperty( '_MDAT' ) );
+
+ $this->assertFalse(
+ $instance->hasRestriction()
+ );
+ }
+
+ public function testRestrictionForUserPropertyOnFalseCreateProtectionRight() {
+
+ $instance = new PropertyRestrictionExaminer();
+
+ $instance->setCreateProtectionRight( false );
+ $instance->setUser( $this->user );
+
+ $instance->checkRestriction( new DIProperty( 'Foo' ) );
+
+ $this->assertFalse(
+ $instance->hasRestriction()
+ );
+ }
+
+ public function testRestrictionForUserPropertyOnCreateProtectionRight() {
+
+ $instance = new PropertyRestrictionExaminer();
+
+ $instance->setCreateProtectionRight( 'foo' );
+ $instance->setUser( $this->user );
+
+ $instance->checkRestriction( new DIProperty( 'Foo' ) );
+
+ $this->assertTrue(
+ $instance->hasRestriction()
+ );
+ }
+
+ public function testRestrictionForUserPropertyOnCreateProtectionRightWithAllowedUser() {
+
+ $right = 'bar';
+
+ $this->user->expects( $this->once() )
+ ->method( 'isAllowed' )
+ ->with( $this->equalTo( $right ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new PropertyRestrictionExaminer();
+
+ $instance->setCreateProtectionRight( $right );
+ $instance->setUser( $this->user );
+
+ $instance->checkRestriction( new DIProperty( 'Foo' ) );
+
+ $this->assertFalse(
+ $instance->hasRestriction()
+ );
+ }
+
+ public function testDeclarativePropertyOnMainNamespace() {
+
+ $instance = new PropertyRestrictionExaminer();
+
+ $instance->checkRestriction(
+ new DIProperty( '_TYPE' ),
+ DIWikiPage::newFromText( 'Bar', NS_MAIN )
+ );
+
+ $this->assertTrue(
+ $instance->hasRestriction()
+ );
+ }
+
+ public function testDeclarativePropertyOnPropertyNamespace() {
+
+ $instance = new PropertyRestrictionExaminer();
+
+ $instance->checkRestriction(
+ new DIProperty( '_TYPE' ),
+ DIWikiPage::newFromText( 'Bar', SMW_NS_PROPERTY )
+ );
+
+ $this->assertFalse(
+ $instance->hasRestriction()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationLookupTest.php
new file mode 100644
index 00000000..071514c2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationLookupTest.php
@@ -0,0 +1,486 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataItemFactory;
+use SMW\PropertySpecificationLookup;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDataItem as DataItem;
+
+/**
+ * @covers \SMW\PropertySpecificationLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class PropertySpecificationLookupTest extends \PHPUnit_Framework_TestCase {
+
+ private $blobStore;
+ private $dataItemFactory;
+ private $testEnvironment;
+ private $cachedPropertyValuesPrefetcher;
+ private $intermediaryMemoryCache;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->cachedPropertyValuesPrefetcher = $this->getMockBuilder( '\SMW\CachedPropertyValuesPrefetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->intermediaryMemoryCache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore = $this->getMockBuilder( '\Onoi\BlobStore\BlobStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataItemFactory = new DataItemFactory();
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\PropertySpecificationLookup',
+ new PropertySpecificationLookup( $this->cachedPropertyValuesPrefetcher, $this->intermediaryMemoryCache )
+ );
+ }
+
+ public function testGetSpecification() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( 'Bar' ) ),
+ $this->anything() );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $instance->getSpecification(
+ $property,
+ $this->dataItemFactory->newDIProperty( 'Bar' )
+ );
+ }
+
+ public function testGetFieldList() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'RecordProperty' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_LIST' ) ),
+ $this->anything() )
+ ->will(
+ $this->returnValue( [
+ $this->dataItemFactory->newDIBlob( 'Foo' ),
+ $this->dataItemFactory->newDIBlob( 'abc;123' ) ] ) );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ 'abc;123',
+ $instance->getFieldListBy( $property )
+ );
+ }
+
+ public function testGetPreferredPropertyLabel() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'SomeProperty' );
+ $property->setPropertyTypeId( '_mlt_rec' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_PPLB' ) ),
+ $this->anything() );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->getPreferredPropertyLabelBy( $property )
+ );
+ }
+
+ public function testGetPropertyFromDisplayTitle() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'queryPropertyValuesFor' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIWikiPage( 'Foo' ) ] ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ $property,
+ $instance->getPropertyFromDisplayTitle( 'abc' )
+ );
+ }
+
+ public function testHasUniquenessConstraint() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_PVUC' ) ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBoolean( true ) ] ) );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertTrue(
+ $instance->hasUniquenessConstraint( $property )
+ );
+ }
+
+ public function testGetExternalFormatterUri() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_PEFU' ) ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIUri( 'http', 'example.org/$1' ) ] ) );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertInstanceOf(
+ DataItem::class,
+ $instance->getExternalFormatterUri( $property )
+ );
+ }
+
+ public function testGetAllowedPattern() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Has allowed pattern' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_PVAP' ) ),
+ $this->anything() )
+ ->will(
+ $this->returnValue( [ $this->dataItemFactory->newDIBlob( 'IPv4' ) ] ) );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ 'IPv4',
+ $instance->getAllowedPatternBy( $property )
+ );
+ }
+
+ public function testGetAllowedListValueBy() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Has list' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_PVALI' ) ),
+ $this->anything() )
+ ->will(
+ $this->returnValue( [ $this->dataItemFactory->newDIBlob( 'Foo' ) ] ) );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ [ 'Foo' ],
+ $instance->getAllowedListValues( $property )
+ );
+ }
+
+ public function testGetAllowedValues() {
+
+ $expected = [
+ $this->dataItemFactory->newDIBlob( 'A' ),
+ $this->dataItemFactory->newDIBlob( 'B' )
+ ];
+
+ $property = $this->dataItemFactory->newDIProperty( 'Has allowed values' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_PVAL' ) ),
+ $this->anything() )
+ ->will( $this->returnValue( $expected ) );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getAllowedValues( $property )
+ );
+ }
+
+ public function testGetDisplayPrecision() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_PREC' ) ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDINumber( -2.3 ) ] ) );
+
+ $this->intermediaryMemoryCache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ 2,
+ $instance->getDisplayPrecision( $property )
+ );
+ }
+
+ public function testgetDisplayUnits() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_UNIT' ) ),
+ $this->anything() )
+ ->will( $this->returnValue( [
+ $this->dataItemFactory->newDIBlob( 'abc,def' ),
+ $this->dataItemFactory->newDIBlob( '123' ) ] ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ [ 'abc', 'def', '123' ],
+ $instance->getDisplayUnits( $property )
+ );
+ }
+
+ public function testGetPropertyDescriptionForPredefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getBlobStore' )
+ ->will( $this->returnValue( $this->blobStore ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getPropertyDescriptionByLanguageCode( $property )
+ );
+ }
+
+ public function testGetPropertyDescriptionForPredefinedPropertyViaCacheForLanguageCode() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->once() )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'pdesc:en:0' ) )
+ ->will( $this->returnValue( 1001 ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getBlobStore' )
+ ->will( $this->returnValue( $this->blobStore ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ 1001,
+ $instance->getPropertyDescriptionByLanguageCode( $property, 'en' )
+ );
+ }
+
+ public function testTryToGetLocalPropertyDescriptionForUserdefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $pdesc = $this->dataItemFactory->newDIProperty( '_PDESC' );
+ $pdesc->setPropertyTypeId( '_mlt_rec' );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [
+ $this->dataItemFactory->newDIContainer( ContainerSemanticData::makeAnonymousContainer() ) ] ) );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getBlobStore' )
+ ->will( $this->returnValue( $this->blobStore ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getPropertyDescriptionByLanguageCode( $property )
+ );
+ }
+
+ public function testGetPropertyGroup() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $ppgr = $this->dataItemFactory->newDIProperty( '_PPGR' );
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Bar', NS_CATEGORY );
+ $bool = $this->dataItemFactory->newDIBoolean( true );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->at( 0 ) )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $property->getDiWikiPage() ),
+ $this->anything(),
+ $this->anything() )
+ ->will( $this->returnValue( [ $dataItem ] ) );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->at( 1 ) )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $dataItem ),
+ $this->equalTo( $ppgr ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $bool ] ) );
+
+ $instance = new PropertySpecificationLookup(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->intermediaryMemoryCache
+ );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->getPropertyGroup( $property )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqExaminerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqExaminerTest.php
new file mode 100644
index 00000000..14f8b58c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqExaminerTest.php
@@ -0,0 +1,331 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataItemFactory;
+use SMW\PropertySpecificationReqExaminer;
+use SMW\SemanticData;
+
+/**
+ * @covers \SMW\PropertySpecificationReqExaminer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertySpecificationReqExaminerTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $protectionValidator;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->protectionValidator = $this->getMockBuilder( '\SMW\Protection\ProtectionValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertySpecificationReqExaminer::class,
+ new PropertySpecificationReqExaminer( $this->store, $this->protectionValidator )
+ );
+ }
+
+ /**
+ * @dataProvider propertyProvider
+ */
+ public function testCheck( $property, $semanticData, $expected ) {
+
+ $instance = new PropertySpecificationReqExaminer(
+ $this->store,
+ $this->protectionValidator
+ );
+
+ $instance->setSemanticData( $semanticData );
+
+ $this->assertEquals(
+ $expected,
+ $instance->check( $property )
+ );
+ }
+
+ public function testCheckDisabledEditProtectionRight() {
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'getEditProtectionRight' )
+ ->will( $this->returnValue( false ) );
+
+ $property = $this->dataItemFactory->newDIProperty( '_EDIP' );
+
+ $instance = new PropertySpecificationReqExaminer(
+ $this->store,
+ $this->protectionValidator
+ );
+
+ $this->assertEquals(
+ [
+ 'warning',
+ 'smw-edit-protection-disabled',
+ 'Is edit protected'
+ ],
+ $instance->check( $property )
+ );
+ }
+
+ public function testCheckEnabledCreateProtectionRight() {
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'hasCreateProtection' )
+ ->will( $this->returnValue( true ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'getCreateProtectionRight' )
+ ->will( $this->returnValue( 'foo' ) );
+
+ $property = $this->dataItemFactory->newDIProperty( 'Bar' );
+
+ $instance = new PropertySpecificationReqExaminer(
+ $this->store,
+ $this->protectionValidator
+ );
+
+ $this->assertEquals(
+ [
+ 'warning',
+ 'smw-create-protection',
+ 'Bar',
+ 'foo'
+ ],
+ $instance->check( $property )
+ );
+ }
+
+ public function testCheckEnabledEditProtectionRight() {
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'hasEditProtection' )
+ ->will( $this->returnValue( true ) );
+
+ $this->protectionValidator->expects( $this->any() )
+ ->method( 'getEditProtectionRight' )
+ ->will( $this->returnValue( 'foo' ) );
+
+ $property = $this->dataItemFactory->newDIProperty( 'Bar' );
+
+ $instance = new PropertySpecificationReqExaminer(
+ $this->store,
+ $this->protectionValidator
+ );
+
+ $this->assertEquals(
+ [
+ 'error',
+ 'smw-edit-protection',
+ 'foo'
+ ],
+ $instance->check( $property )
+ );
+ }
+
+ public function testCheckImportedVocabTypeMismatch() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $semanticData = new SemanticData(
+ $property->getDIWikiPage()
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $this->dataItemFactory->newDIProperty( '_TYPE' ),
+ $this->dataItemFactory->newDIProperty( 'Bar' )
+ );
+
+ $semanticData->setOption(
+ \SMW\PropertyAnnotators\MandatoryTypePropertyAnnotator::IMPO_REMOVED_TYPE,
+ $this->dataItemFactory->newDIProperty( '_TYPE' )
+ );
+
+ $instance = new PropertySpecificationReqExaminer(
+ $this->store,
+ $this->protectionValidator
+ );
+
+ $instance->setSemanticData( $semanticData );
+
+ $this->assertEquals(
+ [
+ 'warning',
+ 'smw-property-req-violation-import-type',
+ 'Foo'
+ ],
+ $instance->check( $property )
+ );
+ }
+
+ public function testCheckChangePropagation() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $semanticData = new SemanticData(
+ $property->getDIWikiPage()
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $this->dataItemFactory->newDIProperty( \SMW\DIProperty::TYPE_CHANGE_PROP ),
+ $this->dataItemFactory->newDIBlob( '...' )
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $instance = new PropertySpecificationReqExaminer(
+ $store,
+ $this->protectionValidator
+ );
+
+ $this->assertEquals(
+ [
+ 'error',
+ 'smw-property-req-violation-change-propagation-locked-error',
+ 'Foo'
+ ],
+ $instance->check( $property )
+ );
+ }
+
+ public function testCheckChangePropagationAsWarning() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $semanticData = new SemanticData(
+ $property->getDIWikiPage()
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $this->dataItemFactory->newDIProperty( \SMW\DIProperty::TYPE_CHANGE_PROP ),
+ $this->dataItemFactory->newDIBlob( '...' )
+ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $instance = new PropertySpecificationReqExaminer(
+ $store,
+ $this->protectionValidator
+ );
+
+ $instance->setChangePropagationProtection( false );
+
+ $this->assertEquals(
+ [
+ 'warning',
+ 'smw-property-req-violation-change-propagation-locked-warning',
+ 'Foo'
+ ],
+ $instance->check( $property )
+ );
+ }
+
+ public function propertyProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' ),
+ $semanticData,
+ ''
+ ];
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( '_MDAT' ),
+ $semanticData,
+ ''
+ ];
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'hasProperty' )
+ ->will( $this->returnValue( false ) );
+
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_ref_rec' );
+
+ $provider[] = [
+ $property,
+ $semanticData,
+ [
+ 'error',
+ 'smw-property-req-violation-missing-fields',
+ 'Foo',
+ 'Reference'
+ ]
+ ];
+
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_rec' );
+
+ $provider[] = [
+ $property,
+ $semanticData,
+ [
+ 'error',
+ 'smw-property-req-violation-missing-fields',
+ 'Foo',
+ 'Record'
+ ]
+ ];
+
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_eid' );
+
+ $provider[] = [
+ $property,
+ $semanticData,
+ [
+ 'error',
+ 'smw-property-req-violation-missing-formatter-uri',
+ 'Foo'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqMsgBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqMsgBuilderTest.php
new file mode 100644
index 00000000..65a0b854
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/PropertySpecificationReqMsgBuilderTest.php
@@ -0,0 +1,236 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataItemFactory;
+use SMW\ProcessingErrorMsgHandler;
+use SMW\PropertySpecificationReqMsgBuilder;
+use SMW\SemanticData;
+
+/**
+ * @covers \SMW\PropertySpecificationReqMsgBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertySpecificationReqMsgBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $propertyTableInfoFetcher;
+ private $propertySpecificationReqExaminer;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $entityManager = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyTableInfoFetcher', 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $this->propertyTableInfoFetcher ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $entityManager ) );
+
+ $this->propertySpecificationReqExaminer = $this->getMockBuilder( '\SMW\PropertySpecificationReqExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertySpecificationReqMsgBuilder::class,
+ new PropertySpecificationReqMsgBuilder( $this->store, $this->propertySpecificationReqExaminer )
+ );
+ }
+
+ /**
+ * @dataProvider propertyProvider
+ */
+ public function testCreateMessage( $property ) {
+
+ $instance = new PropertySpecificationReqMsgBuilder(
+ $this->store,
+ $this->propertySpecificationReqExaminer
+ );
+
+ $instance->check( $property );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getMessage()
+ );
+ }
+
+ public function testFindErrMessages() {
+
+ $dataItemFactory = new DataItemFactory();
+ $subject = $dataItemFactory->newDIWikiPage( 'Test', NS_MAIN );
+
+ $semanticData = new SemanticData(
+ $subject
+ );
+
+ $processingErrorMsgHandler = new ProcessingErrorMsgHandler(
+ $subject
+ );
+
+ $processingErrorMsgHandler->addToSemanticData(
+ $semanticData,
+ $processingErrorMsgHandler->newErrorContainerFromMsg( [ 'testFindErrMessages' ] )
+ );
+
+ $instance = new PropertySpecificationReqMsgBuilder(
+ $this->store,
+ $this->propertySpecificationReqExaminer
+ );
+
+ $instance->setSemanticData( $semanticData );
+
+ $instance->check(
+ $dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $this->assertContains(
+ 'smw-property-error-list',
+ $instance->getMessage()
+ );
+
+ $this->assertContains(
+ 'testFindErrMessages',
+ $instance->getMessage()
+ );
+ }
+
+ public function testErrorOnCompetingTypes() {
+
+ $dataItemFactory = new DataItemFactory();
+ $subject = $dataItemFactory->newDIWikiPage( 'Test', NS_MAIN );
+
+ $semanticData = new SemanticData(
+ $subject
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $dataItemFactory->newDIProperty( '_TYPE' ),
+ $dataItemFactory->newDIBlob( '_num' )
+ );
+
+ $semanticData->addPropertyObjectValue(
+ $dataItemFactory->newDIProperty( '_TYPE' ),
+ $dataItemFactory->newDIBlob( '_dat' )
+ );
+
+ $instance = new PropertySpecificationReqMsgBuilder(
+ $this->store,
+ $this->propertySpecificationReqExaminer
+ );
+
+ $instance->setSemanticData( $semanticData );
+
+ $instance->check(
+ $dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $this->assertContains(
+ 'smw-property-req-violation-type',
+ $instance->getMessage()
+ );
+ }
+
+ public function testCheckUniqueness() {
+
+ $entityManager = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityManager->expects( $this->any() )
+ ->method( 'isUnique' )
+ ->will( $this->returnValue( false ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyTableInfoFetcher', 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $this->propertyTableInfoFetcher ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $entityManager ) );
+
+ $instance = new PropertySpecificationReqMsgBuilder(
+ $store,
+ $this->propertySpecificationReqExaminer
+ );
+
+ $dataItemFactory = new DataItemFactory();
+
+ $instance->check(
+ $dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $this->assertContains(
+ 'smw-property-uniqueness',
+ $instance->getMessage()
+ );
+ }
+
+ public function testCheckReservedName() {
+
+ $instance = new PropertySpecificationReqMsgBuilder(
+ $this->store,
+ $this->propertySpecificationReqExaminer
+ );
+
+ $instance->setPropertyReservedNameList(
+ [
+ 'Bar'
+ ]
+ );
+
+ $dataItemFactory = new DataItemFactory();
+
+ $instance->check(
+ $dataItemFactory->newDIProperty( 'Bar' )
+ );
+
+ $this->assertContains(
+ 'smw-property-name-reserved',
+ $instance->getMessage()
+ );
+ }
+
+ public function propertyProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( 'Foo' )
+ ];
+
+ $provider[] = [
+ $dataItemFactory->newDIProperty( '_MDAT' )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/EditProtectionUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/EditProtectionUpdaterTest.php
new file mode 100644
index 00000000..0520568d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/EditProtectionUpdaterTest.php
@@ -0,0 +1,233 @@
+<?php
+
+namespace SMW\Tests\Protection;
+
+use SMW\DataItemFactory;
+use SMW\Protection\EditProtectionUpdater;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Protection\EditProtectionUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class EditProtectionUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $wikiPage;
+ private $user;
+ private $spyLogger;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+
+ $this->spyLogger = $testEnvironment->getUtilityFactory()->newSpyLogger();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->wikiPage = $this->getMockBuilder( '\WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ EditProtectionUpdater::class,
+ new EditProtectionUpdater( $this->wikiPage, $this->user )
+ );
+ }
+
+ public function testDoUpdateFromWithNoRestrictionsNoEditProtection() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $this->wikiPage->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $subject->getTitle() ) );
+
+ $this->wikiPage->expects( $this->never() )
+ ->method( 'doUpdateRestrictions' );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new EditProtectionUpdater(
+ $this->wikiPage,
+ $this->user
+ );
+
+ $instance->setEditProtectionRight( 'Foo' );
+ $instance->doUpdateFrom( $semanticData );
+
+ $this->assertFalse(
+ $instance->isRestrictedUpdate()
+ );
+ }
+
+ public function testDoUpdateFromWithNoRestrictionsAnActiveEditProtection() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $this->wikiPage->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $subject->getTitle() ) );
+
+ $this->wikiPage->expects( $this->once() )
+ ->method( 'doUpdateRestrictions' );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBoolean( true ) ] ) );
+
+ $instance = new EditProtectionUpdater(
+ $this->wikiPage,
+ $this->user
+ );
+
+ $instance->setEditProtectionRight( 'Foo' );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->doUpdateFrom( $semanticData );
+
+ $this->assertFalse(
+ $instance->isRestrictedUpdate()
+ );
+
+ $this->assertContains(
+ 'add protection on edit, move',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testDoUpdateFromWithRestrictionsButNoTrueEditProtection() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'isProtected' )
+ ->with( $this->equalTo( 'edit' ) )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->once() )
+ ->method( 'getRestrictions' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ $this->wikiPage->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $this->wikiPage->expects( $this->once() )
+ ->method( 'doUpdateRestrictions' );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBoolean( false ) ] ) );
+
+ $instance = new EditProtectionUpdater(
+ $this->wikiPage,
+ $this->user
+ );
+
+ $instance->setEditProtectionRight( 'Foo' );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->doUpdateFrom( $semanticData );
+
+ $this->assertFalse(
+ $instance->isRestrictedUpdate()
+ );
+
+ $this->assertContains(
+ 'remove protection on edit, move',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+ public function testDoUpdateFromWithRestrictionsAnActiveEditProtection() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_EDIP' );
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'isProtected' )
+ ->with( $this->equalTo( 'edit' ) )
+ ->will( $this->returnValue( true ) );
+
+ $title->expects( $this->once() )
+ ->method( 'getRestrictions' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ $this->wikiPage->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $this->wikiPage->expects( $this->never() )
+ ->method( 'doUpdateRestrictions' );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with( $this->equalTo( $property ) )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBoolean( true ) ] ) );
+
+ $instance = new EditProtectionUpdater(
+ $this->wikiPage,
+ $this->user
+ );
+
+ $instance->setEditProtectionRight( 'Foo' );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->doUpdateFrom( $semanticData );
+
+ $this->assertFalse(
+ $instance->isRestrictedUpdate()
+ );
+
+ $this->assertContains(
+ 'Status already set, no update required',
+ $this->spyLogger->getMessagesAsString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/ProtectionValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/ProtectionValidatorTest.php
new file mode 100644
index 00000000..d39c68c2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Protection/ProtectionValidatorTest.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace SMW\Tests\Protection;
+
+use SMW\DataItemFactory;
+use SMW\Protection\ProtectionValidator;
+
+/**
+ * @covers \SMW\Protection\ProtectionValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ProtectionValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $cachedPropertyValuesPrefetcher;
+ private $cache;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->cachedPropertyValuesPrefetcher = $this->getMockBuilder( '\SMW\CachedPropertyValuesPrefetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ProtectionValidator::class,
+ new ProtectionValidator( $this->cachedPropertyValuesPrefetcher, $this->cache )
+ );
+ }
+
+ public function testSetGetEditProtectionRight() {
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $instance->setEditProtectionRight(
+ 'foo'
+ );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getEditProtectionRight()
+ );
+ }
+
+ public function testHasEditProtectionOnNamespace() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN, '', 'Bar' );
+ $property = $this->dataItemFactory->newDIProperty( '_EDIP' );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( false ) );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $subject->asBase() ),
+ $this->equalTo( $property ) )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBoolean( true ) ] ) );
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $instance->setEditProtectionRight(
+ 'foo'
+ );
+
+ $this->assertTrue(
+ $instance->hasEditProtectionOnNamespace( $subject->getTitle() )
+ );
+ }
+
+ public function testHasProtection() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN, '', 'Bar' );
+ $property = $this->dataItemFactory->newDIProperty( '_EDIP' );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( false ) );
+
+ $this->cachedPropertyValuesPrefetcher->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $subject->asBase() ),
+ $this->equalTo( $property ) )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBoolean( true ) ] ) );
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $this->assertTrue(
+ $instance->hasProtection( $subject->getTitle() )
+ );
+ }
+
+ public function testHasProtectionFromCache() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN, '', 'Bar' );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( true ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $this->assertFalse(
+ $instance->hasProtection( $subject->getTitle() )
+ );
+ }
+
+ public function testHasChangePropagationProtectionOnCategory_FromCache() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_CATEGORY );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( true ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $this->assertFalse(
+ $instance->hasChangePropagationProtection( $subject->getTitle() )
+ );
+ }
+
+ public function testNoChangePropagationProtectionOnCategory_FromCache() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_CATEGORY );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->will( $this->returnValue( true ) );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $this->assertTrue(
+ $instance->hasChangePropagationProtection( $subject->getTitle() )
+ );
+ }
+
+ public function testNoChangePropagationProtectionOnCategory_WithFalseSetting() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_CATEGORY );
+
+ $this->cache->expects( $this->never() )
+ ->method( 'contains' );
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $instance->setChangePropagationProtection(
+ false
+ );
+
+ $this->assertFalse(
+ $instance->hasChangePropagationProtection( $subject->getTitle() )
+ );
+ }
+
+ public function testSetGetCreateProtectionRight() {
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $instance->setCreateProtectionRight(
+ 'foo'
+ );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getCreateProtectionRight()
+ );
+ }
+
+ public function testHasCreateProtection() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'userCan' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new ProtectionValidator(
+ $this->cachedPropertyValuesPrefetcher,
+ $this->cache
+ );
+
+ $instance->setCreateProtectionRight(
+ 'foo'
+ );
+
+ $this->assertTrue(
+ $instance->hasCreateProtection( $title )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DebugFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DebugFormatterTest.php
new file mode 100644
index 00000000..4e0fc750
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DebugFormatterTest.php
@@ -0,0 +1,149 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\Query\DebugFormatter;
+
+/**
+ * @covers \SMW\Query\DebugFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class DebugFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testFormatDebugOutputWithoutQuery() {
+
+ $instance = new DebugFormatter();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getStringFrom( 'foo', [], null )
+ );
+ }
+
+ public function testExplainFormat() {
+
+ DebugFormatter::setExplainFormat( DebugFormatter::JSON_FORMAT );
+
+ $this->assertEquals(
+ 'FORMAT=json',
+ DebugFormatter::getFormat( 'mysql' )
+ );
+ }
+
+ public function testFormatDebugOutputWithQuery() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new DebugFormatter();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getStringFrom( 'foo', [], $query )
+ );
+ }
+
+ /**
+ * @dataProvider sqlExplainFormatProvider
+ */
+ public function testFormatSQLExplainOutput( $type, $res ) {
+
+ $instance = new DebugFormatter();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->prettifyExplain( $type, $res )
+ );
+ }
+
+ public function testFormatSPARQLStatement() {
+
+ $instance = new DebugFormatter();
+
+ $sparql = '';
+
+ $this->assertInternalType(
+ 'string',
+ $instance->prettifySparql( $sparql )
+ );
+
+ $this->assertEquals(
+ '<div class="smwpre">&#91;&#x003A;&#x0020;&#x3C;Foo&#x3E;&#x0020;]</div>',
+ $instance->prettifySparql( '[: <Foo> ]' )
+ );
+ }
+
+ public function testFormatSQLStatement() {
+
+ $instance = new DebugFormatter();
+
+ $sql = '';
+ $alias = '';
+
+ $this->assertInternalType(
+ 'string',
+ $instance->prettifySql( $sql, $alias )
+ );
+ }
+
+ public function sqlExplainFormatProvider() {
+
+ $row = [
+ 'id' => '',
+ 'select_type' => '',
+ 'table' => '',
+ 'type' => '',
+ 'possible_keys' => '',
+ 'key' => '',
+ 'key_len' => '',
+ 'ref' => '',
+ 'rows' => '',
+ 'Extra' => ''
+ ];
+
+ $provider[] = [
+ 'mysql',
+ [ (object)$row ]
+ ];
+
+ $provider[] = [
+ 'postgres',
+ [ [ 'QUERY PLAN' => '' ] ]
+ ];
+
+ $provider[] = [
+ 'sqlite',
+ ''
+ ];
+
+ $row = [
+ 'EXPLAIN' => 'Foooooooo'
+ ];
+
+ $provider[] = [
+ 'mysql',
+ [ (object)$row ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DeferredTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DeferredTest.php
new file mode 100644
index 00000000..73ee4df8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DeferredTest.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\Query\Deferred;
+
+/**
+ * @covers \SMW\Query\Deferred
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DeferredTest extends \PHPUnit_Framework_TestCase {
+
+ public function testRegisterResourceModules() {
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'addModuleStyles' );
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'addModules' );
+
+ Deferred::registerResources( $parserOutput );
+ }
+
+ public function testBuildHTML() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertContains(
+ 'smw-deferred-query',
+ Deferred::buildHTML( $query )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DescriptionFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DescriptionFactoryTest.php
new file mode 100644
index 00000000..eb4041e5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/DescriptionFactoryTest.php
@@ -0,0 +1,371 @@
+<?php
+
+namespace SMW\Tests\Query\Parser;
+
+use SMW\DataItemFactory;
+use SMW\DataValues\ValueFormatters\MonolingualTextValueFormatter;
+use SMW\Query\DescriptionFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers SMW\Query\DescriptionFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DescriptionFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\Query\DescriptionFactory',
+ new DescriptionFactory()
+ );
+ }
+
+ public function testCanConstructValueDescription() {
+
+ $dataItem = $this->getMockBuilder( '\SMWDataItem' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ $instance->newValueDescription( $dataItem )
+ );
+ }
+
+ public function testCanConstructSomeProperty() {
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\SomeProperty',
+ $instance->newSomeProperty( $property, $description )
+ );
+ }
+
+ public function testCanConstructThingDescription() {
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ThingDescription',
+ $instance->newThingDescription()
+ );
+ }
+
+ public function testCanConstructDisjunction() {
+
+ $descriptions = [];
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\SomeProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->once() )
+ ->method( 'getPrintRequests' )
+ ->will( $this->returnValue( [] ) );
+
+ $descriptions[] = $description;
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->once() )
+ ->method( 'getPrintRequests' )
+ ->will( $this->returnValue( [] ) );
+
+ $descriptions[] = $description;
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Disjunction',
+ $instance->newDisjunction( $descriptions )
+ );
+ }
+
+ public function testCanConstructConjunction() {
+
+ $descriptions = [];
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\SomeProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->once() )
+ ->method( 'getPrintRequests' )
+ ->will( $this->returnValue( [] ) );
+
+ $descriptions[] = $description;
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->once() )
+ ->method( 'getPrintRequests' )
+ ->will( $this->returnValue( [] ) );
+
+ $descriptions[] = $description;
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ $instance->newConjunction( $descriptions )
+ );
+ }
+
+ public function testCanConstructNamespaceDescription() {
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\NamespaceDescription',
+ $instance->newNamespaceDescription( SMW_NS_PROPERTY )
+ );
+ }
+
+ public function testCanConstructClassDescription() {
+
+ $category = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ClassDescription',
+ $instance->newClassDescription( $category )
+ );
+ }
+
+ public function testCanConstructClassDescription_Categories() {
+
+ $category_1 = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $category_2 = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ClassDescription',
+ $instance->newClassDescription( [ $category_1, $category_2 ] )
+ );
+ }
+
+ public function testCanConstructConceptDescription() {
+
+ $concept = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ConceptDescription',
+ $instance->newConceptDescription( $concept )
+ );
+ }
+
+ public function testCanConstructDescriptionFromInvalidDataValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ThingDescription',
+ $instance->newFromDataValue( $dataValue )
+ );
+ }
+
+ public function testCanConstructDescriptionFromValidDataValue() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid', 'getProperty', 'getDataItem', 'getWikiValue' ] )
+ ->getMockForAbstractClass();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Foo' ) ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar' ) ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getWikiValue' )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\SomeProperty',
+ $instance->newFromDataValue( $dataValue )
+ );
+ }
+
+ public function testCanConstructDescriptionFromMonolingualTextValue() {
+
+ $containerSemanticData = $this->getMockBuilder( '\SMWContainerSemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $containerSemanticData->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBlob( 'Bar' ) ] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMW\DataValues\MonolingualTextValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid', 'getProperty', 'getDataItem' ] )
+ ->getMock();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIContainer( $containerSemanticData ) ) );
+
+ $monolingualTextValueFormatter = new MonolingualTextValueFormatter();
+ $monolingualTextValueFormatter->setDataValue( $dataValue );
+
+ $monolingualTextValueParser = $this->getMockBuilder( '\SMW\DataValues\ValueParsers\MonolingualTextValueParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValueServiceFactory->expects( $this->atLeastOnce() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $monolingualTextValueFormatter ) );
+
+ $dataValueServiceFactory->expects( $this->atLeastOnce() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( $monolingualTextValueParser ) );
+
+ $dataValue->setDataValueServiceFactory(
+ $dataValueServiceFactory
+ );
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ $instance->newFromDataValue( $dataValue )
+ );
+ }
+
+ public function testCanConstructDescriptionFromMonolingualTextValueWithProperty() {
+
+ $containerSemanticData = $this->getMockBuilder( '\SMWContainerSemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $containerSemanticData->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIBlob( 'Bar' ) ] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMW\DataValues\MonolingualTextValue' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'isValid', 'getProperty', 'getDataItem' ] )
+ ->getMock();
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Foo' ) ) );
+
+ $dataValue->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIContainer( $containerSemanticData ) ) );
+
+ $monolingualTextValueFormatter = new MonolingualTextValueFormatter();
+ $monolingualTextValueFormatter->setDataValue( $dataValue );
+
+ $monolingualTextValueParser = $this->getMockBuilder( '\SMW\DataValues\ValueParsers\MonolingualTextValueParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValueServiceFactory = $this->getMockBuilder( '\SMW\Services\DataValueServiceFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValueServiceFactory->expects( $this->atLeastOnce() )
+ ->method( 'getValueFormatter' )
+ ->will( $this->returnValue( $monolingualTextValueFormatter ) );
+
+ $dataValueServiceFactory->expects( $this->atLeastOnce() )
+ ->method( 'getValueParser' )
+ ->will( $this->returnValue( $monolingualTextValueParser ) );
+
+ $dataValue->setDataValueServiceFactory(
+ $dataValueServiceFactory
+ );
+
+ $instance = new DescriptionFactory();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\SomeProperty',
+ $instance->newFromDataValue( $dataValue )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Exception/ResultFormatNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Exception/ResultFormatNotFoundExceptionTest.php
new file mode 100644
index 00000000..e6db988c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Exception/ResultFormatNotFoundExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Query\Exception;
+
+use SMW\Query\Exception\ResultFormatNotFoundException;
+
+/**
+ * @covers \SMW\Query\Exception\ResultFormatNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ResultFormatNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new ResultFormatNotFoundException();
+
+ $this->assertInstanceof(
+ '\SMW\Query\Exception\ResultFormatNotFoundException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ExcerptsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ExcerptsTest.php
new file mode 100644
index 00000000..9dae22ae
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ExcerptsTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\DIWikiPage;
+use SMW\Query\Excerpts;
+
+/**
+ * @covers \SMW\Query\Excerpts
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ExcerptsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Excerpts::class,
+ new Excerpts()
+ );
+ }
+
+ public function testAddExcerpt() {
+
+ $instance = new Excerpts();
+
+ $instance->addExcerpt( 'Foo', 0.1 );
+
+ $this->assertEquals(
+ 0.1,
+ $instance->getExcerpt( 'Foo' )
+ );
+
+ $this->assertFalse(
+ $instance->getExcerpt( 'Bar' )
+ );
+ }
+
+ public function testAddExcerpt_DIWikiPage() {
+
+ $dataItem = DIWikiPage::newFromText( 'Bar' );
+ $instance = new Excerpts();
+
+ $instance->addExcerpt( $dataItem, 10 );
+
+ $this->assertEquals(
+ 10,
+ $instance->getExcerpt( $dataItem )
+ );
+ }
+
+ public function testGetExcerpts() {
+
+ $instance = new Excerpts();
+
+ $instance->addExcerpt( 'Foo', '...' );
+ $instance->addExcerpt( 'Bar', 1001 );
+
+ $this->assertEquals(
+ [
+ [ 'Foo', '...' ],
+ [ 'Bar', 1001 ]
+ ],
+ $instance->getExcerpts()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ClassDescriptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ClassDescriptionTest.php
new file mode 100644
index 00000000..6e71a51f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ClassDescriptionTest.php
@@ -0,0 +1,280 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\ThingDescription;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Query\Language\ClassDescription
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ClassDescriptionTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $cat_name;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->cat_name = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );;
+ }
+
+ public function testCanConstruct() {
+
+ $class = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ClassDescription',
+ new ClassDescription( $class )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ClassDescription',
+ new \SMWClassDescription( $class )
+ );
+ }
+
+ public function testConstructThrowsException() {
+
+ $this->setExpectedException( 'Exception' );
+
+ new ClassDescription( new \stdClass );
+ }
+
+ public function testCommonMethods() {
+
+ $ns = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+
+ $class = new DIWikiPage( 'Foo', NS_CATEGORY );
+ $instance = new ClassDescription( $class );
+
+ $this->assertEquals( [ $class ], $instance->getCategories() );
+
+ $this->assertEquals( "[[{$ns}:Foo]]", $instance->getQueryString() );
+ $this->assertEquals( " <q>[[{$ns}:Foo]]</q> ", $instance->getQueryString( true ) );
+
+ $this->assertEquals( false, $instance->isSingleton() );
+ $this->assertEquals( [], $instance->getPrintRequests() );
+
+ $this->assertEquals( 1, $instance->getSize() );
+ $this->assertEquals( 0, $instance->getDepth() );
+ $this->assertEquals( 2, $instance->getQueryFeatures() );
+ }
+
+ public function testAddDescription() {
+
+ $ns = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+
+ $instance = new ClassDescription( new DIWikiPage( 'Foo', NS_CATEGORY ) );
+ $instance->addDescription( new ClassDescription( new DIWikiPage( 'Bar', NS_CATEGORY ) ) );
+
+ $this->assertEquals(
+ "[[{$ns}:Foo||Bar]]",
+ $instance->getQueryString()
+ );
+
+ $this->assertEquals(
+ " <q>[[{$ns}:Foo||Bar]]</q> ",
+ $instance->getQueryString( true )
+ );
+ }
+
+ public function testAddClass() {
+
+ $ns = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+
+ $instance = new ClassDescription( new DIWikiPage( 'Foo', NS_CATEGORY ) );
+ $instance->addClass( new DIWikiPage( 'Bar', NS_CATEGORY ) );
+
+ $this->assertEquals(
+ "[[{$ns}:Foo||Bar]]",
+ $instance->getQueryString()
+ );
+
+ $this->assertEquals(
+ " <q>[[{$ns}:Foo||Bar]]</q> ",
+ $instance->getQueryString( true )
+ );
+ }
+
+ public function testIsMergableDescription() {
+
+ $cat = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $instance = new ClassDescription(
+ $cat
+ );
+
+ $this->assertTrue(
+ $instance->isMergableDescription( new ClassDescription( $cat ) )
+ );
+
+ $instance->isNegation = true;
+
+ $this->assertFalse(
+ $instance->isMergableDescription( new ClassDescription( $cat ) )
+ );
+ }
+
+ public function testClass_Negation() {
+
+ $cat = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $instance = new ClassDescription(
+ $cat
+ );
+
+ $this->assertEquals(
+ "[[{$this->cat_name}:Foo]]",
+ $instance->getQueryString()
+ );
+
+ $instance->isNegation = true;
+
+ $this->assertEquals(
+ "[[{$this->cat_name}:!Foo]]",
+ $instance->getQueryString()
+ );
+
+ $instance->addClass( new DIWikiPage( 'Bar', NS_CATEGORY ) );
+
+ $this->assertEquals(
+ "[[{$this->cat_name}:!Foo||!Bar]]",
+ $instance->getQueryString()
+ );
+ }
+
+ public function testGetFingerprint() {
+
+ $instance = new ClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $instance->addDescription(
+ new ClassDescription( new DIWikiPage( 'Bar', NS_CATEGORY ) )
+ );
+
+ $expected = $instance->getFingerprint();
+
+ // Different position, same hash
+ $instance = new ClassDescription(
+ new DIWikiPage( 'Bar', NS_CATEGORY )
+ );
+
+ $instance->addDescription(
+ new ClassDescription( new DIWikiPage( 'Foo', NS_CATEGORY ) )
+ );
+
+ $this->assertSame(
+ $expected,
+ $instance->getFingerprint()
+ );
+
+ // Adds extra description, changes hash
+ $instance->addDescription(
+ new ClassDescription( new DIWikiPage( 'Foobar', NS_CATEGORY ) )
+ );
+
+ $this->assertNotSame(
+ $expected,
+ $instance->getFingerprint()
+ );
+ }
+
+ public function testPrune() {
+
+ $instance = new ClassDescription( new DIWikiPage( 'Foo', NS_CATEGORY ) );
+
+ $maxsize = 1;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ $instance,
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+
+ $maxsize = 0;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ new ThingDescription(),
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+ }
+
+ public function testStableFingerprint() {
+
+ $instance = new ClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $this->assertSame(
+ 'Cl:c2d00d69a4e9517d075d9adf6aafea6e',
+ $instance->getFingerprint()
+ );
+ }
+
+ public function testHierarchyDepthToBeCeiledOnMaxQSubcategoryDepthSetting() {
+
+ $instance = new ClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $instance->setHierarchyDepth( 9999999 );
+
+ $this->assertSame(
+ $GLOBALS['smwgQSubcategoryDepth'],
+ $instance->getHierarchyDepth()
+ );
+ }
+
+ public function testGetQueryStringWithHierarchyDepth() {
+
+ $ns = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+
+ $instance = new ClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $instance->setHierarchyDepth( 1 );
+
+ $this->assertSame(
+ "[[$ns:Foo|+depth=1]]",
+ $instance->getQueryString()
+ );
+ }
+
+ public function testVaryingHierarchyDepthCausesDifferentFingerprint() {
+
+ $instance = new ClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $instance->setHierarchyDepth( 9999 );
+ $expected = $instance->getFingerprint();
+
+ $instance = new ClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $this->assertNotSame(
+ $expected,
+ $instance->getFingerprint()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConceptDescriptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConceptDescriptionTest.php
new file mode 100644
index 00000000..b3098817
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConceptDescriptionTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Query\Language\ConceptDescription;
+use SMW\Query\Language\ThingDescription;
+
+/**
+ * @covers \SMW\Query\Language\ConceptDescription
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ConceptDescriptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $concept = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ConceptDescription',
+ new ConceptDescription( $concept )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ConceptDescription',
+ new \SMWConceptDescription( $concept )
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $ns = Localizer::getInstance()->getNamespaceTextById( SMW_NS_CONCEPT );
+
+ $concept = new DIWikiPage( 'Foo', SMW_NS_CONCEPT );
+ $instance = new ConceptDescription( $concept );
+
+ $this->assertEquals( $concept, $instance->getConcept() );
+
+ $this->assertEquals( "[[{$ns}:Foo]]", $instance->getQueryString() );
+ $this->assertEquals( " <q>[[{$ns}:Foo]]</q> ", $instance->getQueryString( true ) );
+
+ $this->assertEquals( false, $instance->isSingleton() );
+ $this->assertEquals( [], $instance->getPrintRequests() );
+
+ $this->assertEquals( 1, $instance->getSize() );
+ $this->assertEquals( 0, $instance->getDepth() );
+ $this->assertEquals( 4, $instance->getQueryFeatures() );
+ }
+
+ public function testGetFingerprint() {
+
+ $instance = new ConceptDescription(
+ new DIWikiPage( 'Foo', SMW_NS_CONCEPT )
+ );
+
+ $expected = $instance->getFingerprint();
+
+ $instance = new ConceptDescription(
+ new DIWikiPage( 'Bar', SMW_NS_CONCEPT )
+ );
+
+ $this->assertNotSame(
+ $expected,
+ $instance->getFingerprint()
+ );
+ }
+
+ public function testPrune() {
+
+ $instance = new ConceptDescription( new DIWikiPage( 'Foo', SMW_NS_CONCEPT ) );
+
+ $maxsize = 1;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ $instance,
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+
+ $maxsize = 0;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ new ThingDescription(),
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConjunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConjunctionTest.php
new file mode 100644
index 00000000..d72aebb0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ConjunctionTest.php
@@ -0,0 +1,254 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+
+/**
+ * @covers \SMW\Query\Language\Conjunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ConjunctionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ new Conjunction()
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ new \SMWConjunction()
+ );
+ }
+
+ /**
+ * @dataProvider conjunctionProvider
+ */
+ public function testCommonMethods( $descriptions, $expected ) {
+
+ $instance = new Conjunction( $descriptions );
+
+ $this->assertEquals(
+ $expected['descriptions'],
+ $instance->getDescriptions()
+ );
+
+ $this->assertEquals(
+ $expected['queryString'],
+ $instance->getQueryString()
+ );
+
+ $this->assertEquals(
+ $expected['queryStringAsValue'],
+ $instance->getQueryString( true )
+ );
+
+ $this->assertEquals(
+ $expected['isSingleton'],
+ $instance->isSingleton()
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->getPrintRequests()
+ );
+
+ $this->assertEquals(
+ $expected['size'],
+ $instance->getSize()
+ );
+
+ $this->assertEquals(
+ $expected['depth'],
+ $instance->getDepth()
+ );
+
+ $this->assertEquals(
+ $expected['queryFeatures'],
+ $instance->getQueryFeatures()
+ );
+ }
+
+ /**
+ * @dataProvider comparativeHashProvider
+ */
+ public function testGetFingerprint( $descriptions, $compareTo, $expected ) {
+
+ $instance = new Conjunction(
+ $descriptions
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getFingerprint() === $compareTo->getFingerprint()
+ );
+ }
+
+ public function conjunctionProvider() {
+
+ $nsHelp = Localizer::getInstance()->getNamespaceTextById( NS_HELP );
+
+ $descriptions = [
+ 'N:cfcd208495d565ef66e7dff9f98764da' => new NamespaceDescription( NS_MAIN ),
+ 'N:c20ad4d76fe97759aa27a0c99bff6710' => new NamespaceDescription( NS_HELP )
+ ];
+
+ $provider[] = [
+ $descriptions,
+ [
+ 'descriptions' => $descriptions,
+ 'queryString' => "[[:+]] [[{$nsHelp}:+]]",
+ 'queryStringAsValue' => " <q>[[:+]] [[{$nsHelp}:+]]</q> ",
+ 'isSingleton' => false,
+ 'queryFeatures' => 24,
+ 'size' => 2,
+ 'depth' => 0
+ ]
+ ];
+
+ $valueDescriptionFoo = new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) );
+ $valueDescriptionBar = new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) );
+ $valueDescriptionYim = new ValueDescription( new DIWikiPage( 'Yim', NS_MAIN ) );
+
+ $descriptions = [
+ $valueDescriptionFoo,
+ new Conjunction( [
+ $valueDescriptionBar,
+ $valueDescriptionYim
+ ] )
+ ];
+
+ $description = [
+ 'V:903e513c13559ffaa66a23270a2922ff' => $valueDescriptionFoo,
+ 'V:246b70c7cb6a9fe4613cad14405b682f' => $valueDescriptionBar,
+ 'V:a3f71a427c6f9533ea1f093ff47bf958' => $valueDescriptionYim
+ ];
+
+ $provider[] = [
+ $descriptions,
+ [
+ 'descriptions' => $description,
+ 'queryString' => '[[:Foo]] [[:Bar]] [[:Yim]]',
+ 'queryStringAsValue' => ' <q>[[:Foo]] [[:Bar]] [[:Yim]]</q> ',
+ 'isSingleton' => true,
+ 'queryFeatures' => 16,
+ 'size' => 3,
+ 'depth' => 0
+ ]
+ ];
+
+ return $provider;
+ }
+
+
+ public function testPrune() {
+
+ $valueDescriptionFoo = new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) );
+ $valueDescriptionBar = new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) );
+
+ $descriptions = [
+ $valueDescriptionFoo,
+ $valueDescriptionBar,
+ ];
+
+ $instance = new Conjunction( $descriptions );
+
+ $maxsize = 1;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ $valueDescriptionFoo,
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+
+ $maxsize = 0;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ new ThingDescription(),
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+ }
+
+ public function comparativeHashProvider() {
+
+ $descriptions = [
+ new NamespaceDescription( NS_MAIN ),
+ new NamespaceDescription( NS_HELP )
+ ];
+
+ $conjunction = new Conjunction(
+ $descriptions
+ );
+
+ $provider[] = [
+ $descriptions,
+ $conjunction,
+ true
+ ];
+
+ // Different order, same hash
+ $descriptions = [
+ new NamespaceDescription( NS_HELP ),
+ new NamespaceDescription( NS_MAIN ) // Changed position
+ ];
+
+ $conjunction = new Conjunction(
+ $descriptions
+ );
+
+ $provider[] = [
+ $descriptions,
+ $conjunction,
+ true
+ ];
+
+ // ThingDescription is neglected
+ $conjunction = new Conjunction(
+ $descriptions
+ );
+
+ $conjunction->addDescription(
+ new ThingDescription()
+ );
+
+ $provider[] = [
+ $descriptions,
+ $conjunction,
+ true
+ ];
+
+ // Adds description === different signature === different hash
+ $conjunction = new Conjunction(
+ $descriptions
+ );
+
+ $conjunction->addDescription(
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) )
+ );
+
+ $provider[] = [
+ $descriptions,
+ $conjunction,
+ false
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/DisjunctionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/DisjunctionTest.php
new file mode 100644
index 00000000..27b3ad3e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/DisjunctionTest.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+
+/**
+ * @covers \SMW\Query\Language\Disjunction
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class DisjunctionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Disjunction',
+ new Disjunction()
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Disjunction',
+ new \SMWDisjunction()
+ );
+ }
+
+ /**
+ * @dataProvider disjunctionProvider
+ */
+ public function testCommonMethods( $descriptions, $expected ) {
+
+ $instance = new Disjunction( $descriptions );
+
+ $this->assertEquals(
+ $expected['descriptions'],
+ $instance->getDescriptions()
+ );
+
+ $this->assertEquals(
+ $expected['queryString'],
+ $instance->getQueryString()
+ );
+
+ $this->assertEquals(
+ $expected['queryStringAsValue'],
+ $instance->getQueryString( true )
+ );
+
+ $this->assertEquals(
+ $expected['isSingleton'],
+ $instance->isSingleton()
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->getPrintRequests()
+ );
+
+ $this->assertEquals(
+ $expected['size'],
+ $instance->getSize()
+ );
+
+ $this->assertEquals(
+ $expected['depth'],
+ $instance->getDepth()
+ );
+
+ $this->assertEquals(
+ $expected['queryFeatures'],
+ $instance->getQueryFeatures()
+ );
+ }
+
+ /**
+ * @dataProvider comparativeHashProvider
+ */
+ public function testGetFingerprint( $descriptions, $compareTo, $expected ) {
+
+ $instance = new Disjunction(
+ $descriptions
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getFingerprint() === $compareTo->getFingerprint()
+ );
+ }
+
+ public function disjunctionProvider() {
+
+ $nsHelp = Localizer::getInstance()->getNamespaceTextById( NS_HELP );
+
+ $descriptions = [
+ 'N:cfcd208495d565ef66e7dff9f98764da' => new NamespaceDescription( NS_MAIN ),
+ 'N:c20ad4d76fe97759aa27a0c99bff6710' => new NamespaceDescription( NS_HELP )
+ ];
+
+ $provider[] = [
+ $descriptions,
+ [
+ 'descriptions' => $descriptions,
+ 'queryString' => " <q>[[:+]] OR [[{$nsHelp}:+]]</q> ",
+ 'queryStringAsValue' => " <q>[[:+]]</q> || <q>[[{$nsHelp}:+]]</q> ",
+ 'isSingleton' => false,
+ 'queryFeatures' => 40,
+ 'size' => 2,
+ 'depth' => 0
+ ]
+ ];
+
+ $descriptions = [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ new Disjunction( [
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) ),
+ new ValueDescription( new DIWikiPage( 'Yim', NS_MAIN ) )
+ ] )
+ ];
+
+ $expectedDescriptions = [
+ 'V:903e513c13559ffaa66a23270a2922ff' => new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ 'V:246b70c7cb6a9fe4613cad14405b682f' => new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) ),
+ 'V:a3f71a427c6f9533ea1f093ff47bf958' => new ValueDescription( new DIWikiPage( 'Yim', NS_MAIN ) )
+ ];
+
+ $provider[] = [
+ $descriptions,
+ [
+ 'descriptions' => $expectedDescriptions,
+ 'queryString' => ' <q>[[:Foo]] OR [[:Bar]] OR [[:Yim]]</q> ',
+ 'queryStringAsValue' => 'Foo||Bar||Yim',
+ 'isSingleton' => false,
+ 'queryFeatures' => 32,
+ 'size' => 3,
+ 'depth' => 0
+ ]
+ ];
+
+ $descriptions = [
+ 'V:903e513c13559ffaa66a23270a2922ff' => new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ 'C:d0da0541e2e099655342be3af203814e' => new Conjunction( [
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) ),
+ new ValueDescription( new DIWikiPage( 'Yim', NS_MAIN ) )
+ ] )
+ ];
+
+ $provider[] = [
+ $descriptions,
+ [
+ 'descriptions' => $descriptions,
+ 'queryString' => ' <q>[[:Foo]] OR [[:Bar]] [[:Yim]]</q> ',
+ 'queryStringAsValue' => 'Foo|| <q>[[:Bar]] [[:Yim]]</q> ',
+ 'isSingleton' => false,
+ 'queryFeatures' => 48,
+ 'size' => 3,
+ 'depth' => 0
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function testPrune() {
+
+ $descriptions = [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) ),
+ ];
+
+ $instance = new Disjunction( $descriptions );
+
+ $maxsize = 2;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ $instance,
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+
+ $maxsize = 0;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ new ThingDescription(),
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+ }
+
+ public function comparativeHashProvider() {
+
+ $descriptions = [
+ new NamespaceDescription( NS_MAIN ),
+ new NamespaceDescription( NS_HELP )
+ ];
+
+ $disjunction = new Disjunction(
+ $descriptions
+ );
+
+ $provider[] = [
+ $descriptions,
+ $disjunction,
+ true
+ ];
+
+ // Different order, same hash
+ $descriptions = [
+ new NamespaceDescription( NS_HELP ),
+ new NamespaceDescription( NS_MAIN ) // Changed position
+ ];
+
+ $disjunction = new Disjunction(
+ $descriptions
+ );
+
+ $provider[] = [
+ $descriptions,
+ $disjunction,
+ true
+ ];
+
+ // ThingDescription forces a different hash
+ $disjunction = new Disjunction(
+ $descriptions
+ );
+
+ $disjunction->addDescription(
+ new ThingDescription()
+ );
+
+ $provider[] = [
+ $descriptions,
+ $disjunction,
+ false
+ ];
+
+ // Adds description === different signature === different hash
+ $disjunction = new Disjunction(
+ $descriptions
+ );
+
+ $disjunction->addDescription(
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) )
+ );
+
+ $provider[] = [
+ $descriptions,
+ $disjunction,
+ false
+ ];
+
+ return $provider;
+ }
+
+ public function testVaryingHierarchyDepthCausesClassDescriptionToYieldDifferentFingerprint() {
+
+ $descriptions = [
+ new ClassDescription( new DIWikiPage( 'Foo', NS_CATEGORY ) )
+ ];
+
+ $instance = new Disjunction(
+ $descriptions
+ );
+
+ $expected = $instance->getFingerprint();
+
+ $descriptions = [
+ new ClassDescription( new DIWikiPage( 'Foo', NS_CATEGORY ) )
+ ];
+
+ $instance = new Disjunction(
+ $descriptions
+ );
+
+ $instance->setHierarchyDepth( 1 );
+
+ $this->assertNotSame(
+ $expected,
+ $instance->getFingerprint()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/NamespaceDescriptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/NamespaceDescriptionTest.php
new file mode 100644
index 00000000..4d35298b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/NamespaceDescriptionTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\Localizer;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\ThingDescription;
+
+/**
+ * @covers \SMW\Query\Language\NamespaceDescription
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class NamespaceDescriptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $namespace = NS_MAIN;
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\NamespaceDescription',
+ new NamespaceDescription( $namespace )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\NamespaceDescription',
+ new \SMWNamespaceDescription( $namespace )
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $namespace = NS_MAIN;
+
+ $instance = new NamespaceDescription( $namespace );
+
+ $this->assertEquals( $namespace, $instance->getNamespace() );
+
+ $this->assertEquals( "[[:+]]", $instance->getQueryString() );
+ $this->assertEquals( " <q>[[:+]]</q> ", $instance->getQueryString( true ) );
+
+ $this->assertEquals( false, $instance->isSingleton() );
+ $this->assertEquals( [], $instance->getPrintRequests() );
+
+ $this->assertEquals( 1, $instance->getSize() );
+ $this->assertEquals( 0, $instance->getDepth() );
+ $this->assertEquals( 8, $instance->getQueryFeatures() );
+ }
+
+ public function testGetQueryStringForCategoryNamespace() {
+
+ $namespace = NS_CATEGORY;
+
+ $ns = Localizer::getInstance()->getNamespaceTextById( $namespace );
+ $instance = new NamespaceDescription( $namespace );
+
+ $this->assertEquals(
+ "[[:{$ns}:+]]",
+ $instance->getQueryString()
+ );
+
+ $this->assertEquals(
+ " <q>[[:{$ns}:+]]</q> ",
+ $instance->getQueryString( true )
+ );
+ }
+
+ public function testPrune() {
+
+ $instance = new NamespaceDescription( NS_MAIN );
+
+ $maxsize = 1;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ $instance,
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+
+ $maxsize = 0;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ new ThingDescription(),
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/SomePropertyTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/SomePropertyTest.php
new file mode 100644
index 00000000..0c3974f9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/SomePropertyTest.php
@@ -0,0 +1,506 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+
+/**
+ * @covers \SMW\Query\Language\SomeProperty
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SomePropertyTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\SomeProperty',
+ new SomeProperty( $property, $description )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\SomeProperty',
+ new \SMWSomeProperty( $property, $description )
+ );
+ }
+
+ /**
+ * @dataProvider somePropertyProvider
+ */
+ public function testCommonMethods( $property, $description, $expected ) {
+
+ $instance = new SomeProperty( $property, $description );
+
+ $this->assertEquals(
+ $expected['property'],
+ $instance->getProperty()
+ );
+
+ $this->assertEquals(
+ $expected['description'],
+ $instance->getDescription()
+ );
+
+ $this->assertEquals(
+ $expected['queryString'],
+ $instance->getQueryString()
+ );
+
+ $this->assertEquals(
+ $expected['queryStringAsValue'],
+ $instance->getQueryString( true )
+ );
+
+ $this->assertEquals(
+ $expected['isSingleton'],
+ $instance->isSingleton()
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->getPrintRequests()
+ );
+
+ $this->assertEquals(
+ $expected['size'],
+ $instance->getSize()
+ );
+
+ $this->assertEquals(
+ $expected['depth'],
+ $instance->getDepth()
+ );
+
+ $this->assertEquals(
+ $expected['queryFeatures'],
+ $instance->getQueryFeatures()
+ );
+ }
+
+ /**
+ * @dataProvider comparativeHashProvider
+ */
+ public function testGetFingerprint( $description, $compareTo, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ $description->getFingerprint() === $compareTo->getFingerprint()
+ );
+ }
+
+ public function somePropertyProvider() {
+
+ #0
+ $property = new DIProperty( 'Foo' );
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN ),
+ $property
+ );
+
+ $provider[] = [
+ $property,
+ $description,
+ [
+ 'property' => $property,
+ 'description' => $description,
+ 'queryString' => "[[Foo::Bar]]",
+ 'queryStringAsValue' => "<q>[[Foo::Bar]]</q>",
+ 'isSingleton' => false,
+ 'queryFeatures' => 1,
+ 'size' => 2,
+ 'depth' => 1
+ ]
+ ];
+
+ #1
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Yui' ),
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ), null )
+ );
+
+ $provider[] = [
+ $property,
+ $description,
+ [
+ 'property' => $property,
+ 'description' => $description,
+ 'queryString' => "[[Foo.Yui::Bar]]",
+ 'queryStringAsValue' => "<q>[[Foo.Yui::Bar]]</q>",
+ 'isSingleton' => false,
+ 'queryFeatures' => 1,
+ 'size' => 3,
+ 'depth' => 2
+ ]
+ ];
+
+ #2
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Yui' ),
+ new NamespaceDescription( NS_MAIN )
+ );
+
+ $provider[] = [
+ $property,
+ $description,
+ [
+ 'property' => $property,
+ 'description' => $description,
+ 'queryString' => "[[Foo.Yui:: <q>[[:+]]</q> ]]",
+ 'queryStringAsValue' => "<q>[[Foo.Yui:: <q>[[:+]]</q> ]]</q>",
+ 'isSingleton' => false,
+ 'queryFeatures' => 9,
+ 'size' => 3,
+ 'depth' => 2
+ ]
+ ];
+
+ #3, 1096
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Yui' ),
+ new SomeProperty(
+ new DIProperty( 'Bar', true ),
+ new NamespaceDescription( NS_MAIN )
+ )
+ );
+
+ $provider[] = [
+ $property,
+ $description,
+ [
+ 'property' => $property,
+ 'description' => $description,
+ 'queryString' => "[[Foo.Yui.-Bar:: <q>[[:+]]</q> ]]",
+ 'queryStringAsValue' => "<q>[[Foo.Yui.-Bar:: <q>[[:+]]</q> ]]</q>",
+ 'isSingleton' => false,
+ 'queryFeatures' => 9,
+ 'size' => 4,
+ 'depth' => 3
+ ]
+ ];
+
+ #4, 1096
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Yui' ),
+ new SomeProperty(
+ new DIProperty( '_SOBJ', true ),
+ new NamespaceDescription( NS_MAIN )
+ )
+ );
+
+ $provider[] = [
+ $property,
+ $description,
+ [
+ 'property' => $property,
+ 'description' => $description,
+ 'queryString' => "[[Foo.Yui.-Has subobject:: <q>[[:+]]</q> ]]",
+ 'queryStringAsValue' => "<q>[[Foo.Yui.-Has subobject:: <q>[[:+]]</q> ]]</q>",
+ 'isSingleton' => false,
+ 'queryFeatures' => 9,
+ 'size' => 4,
+ 'depth' => 3
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function testPrune() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN ),
+ $property
+ );
+
+ $instance = new SomeProperty( $property, $description );
+
+ $maxsize = 2;
+ $maxDepth = 2;
+ $log = [];
+
+ $this->assertEquals(
+ $instance,
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+
+ $this->assertEquals( 0, $maxsize );
+ $this->assertEquals( 1, $maxDepth );
+
+ $maxsize = 0;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ new ThingDescription(),
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+ }
+
+ public function testStableFingerprint() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN ),
+ $property
+ );
+
+ $instance = new SomeProperty(
+ $property,
+ $description
+ );
+
+ $this->assertSame(
+ 'S:8c2cab8d14dcd45d49aadb7fb5ab44a7',
+ $instance->getFingerprint()
+ );
+ }
+
+ public function testHierarchyDepthToBeCeiledOnMaxQSubpropertyDepthSetting() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN ),
+ $property
+ );
+
+ $instance = new SomeProperty(
+ $property,
+ $description
+ );
+
+ $instance->setHierarchyDepth( 9999999 );
+
+ $this->assertSame(
+ $GLOBALS['smwgQSubpropertyDepth'],
+ $instance->getHierarchyDepth()
+ );
+ }
+
+ public function testGetQueryStringWithHierarchyDepth() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN ),
+ $property
+ );
+
+ $instance = new SomeProperty(
+ $property,
+ $description
+ );
+
+ $instance->setHierarchyDepth( 1 );
+
+ $this->assertSame(
+ "[[Foo::Bar|+depth=1]]",
+ $instance->getQueryString()
+ );
+ }
+
+ public function testVaryingHierarchyDepthCausesDifferentFingerprint() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN ),
+ $property
+ );
+
+ $instance = new SomeProperty(
+ $property,
+ $description
+ );
+
+ $instance->setHierarchyDepth( 9999 );
+ $expected = $instance->getFingerprint();
+
+ $instance = new SomeProperty(
+ $property,
+ $description
+ );
+
+ $this->assertNotSame(
+ $expected,
+ $instance->getFingerprint()
+ );
+ }
+
+ public function comparativeHashProvider() {
+
+ // Same property, different description === different hash
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new NamespaceDescription( NS_HELP )
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new NamespaceDescription( NS_MAIN )
+ ),
+ false
+ ];
+
+ // Inverse property, same description === different hash
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo', true ),
+ new NamespaceDescription( NS_MAIN )
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new NamespaceDescription( NS_MAIN )
+ ),
+ false
+ ];
+
+ // Same property, different description === different hash
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo', true ),
+ new NamespaceDescription( NS_MAIN )
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ThingDescription()
+ ),
+ false
+ ];
+
+ // Property.chain, different description === different hash
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo', true ),
+ new ThingDescription()
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ThingDescription()
+ )
+ ),
+ false
+ ];
+
+ // Property.chain, same description === same hash
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ThingDescription()
+ )
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ThingDescription()
+ )
+ ),
+ true
+ ];
+
+ // Property.chain, different description (inverse prop) === different hash
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ThingDescription()
+ )
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo', true ),
+ new ThingDescription()
+ )
+ ),
+ false
+ ];
+
+ // Property.chain, different description === different hash
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ThingDescription()
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ThingDescription()
+ )
+ )
+ ),
+ false
+ ];
+
+ // Property.chain, different description === different hash
+ // "[[Foo.Foo::Foo]]" !== "[[Foo.Foo.Foo::Foo]]"
+ $provider[] = [
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) )
+ )
+ )
+ ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) )
+ )
+ )
+ )
+ ),
+ false
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ThingDescriptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ThingDescriptionTest.php
new file mode 100644
index 00000000..d4051ccc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ThingDescriptionTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\Query\Language\ThingDescription;
+
+/**
+ * @covers \SMW\Query\Language\ThingDescription
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ThingDescriptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ThingDescription',
+ new ThingDescription()
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ThingDescription',
+ new \SMWThingDescription()
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $instance = new ThingDescription();
+
+ $this->assertEquals( '', $instance->getQueryString() );
+ $this->assertEquals( false, $instance->isSingleton() );
+ $this->assertEquals( [], $instance->getPrintRequests() );
+
+ $this->assertEquals( 0, $instance->getSize() );
+ $this->assertEquals( 0, $instance->getDepth() );
+ $this->assertEquals( 0, $instance->getQueryFeatures() );
+ }
+
+ public function testPrune() {
+
+ $instance = new ThingDescription();
+
+ $maxsize = 1;
+ $maxDepth = 1;
+ $log = [];
+
+ $this->assertEquals(
+ $instance,
+ $instance->prune( $maxsize, $maxDepth, $log )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ValueDescriptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ValueDescriptionTest.php
new file mode 100644
index 00000000..b430eba7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Language/ValueDescriptionTest.php
@@ -0,0 +1,223 @@
+<?php
+
+namespace SMW\Tests\Query\Language;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ValueDescription;
+use SMWDINumber as DINumber;
+
+/**
+ * @covers \SMW\Query\Language\ValueDescription
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ValueDescriptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $dataItem = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ new ValueDescription( $dataItem )
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ new \SMWValueDescription( $dataItem )
+ );
+ }
+
+ /**
+ * @dataProvider valueDescriptionProvider
+ */
+ public function testCommonMethods( $dataItem, $property, $comparator, $expected ) {
+
+ $instance = new ValueDescription( $dataItem, $property, $comparator );
+
+ $this->assertEquals(
+ $expected['comparator'],
+ $instance->getComparator()
+ );
+
+ $this->assertEquals(
+ $expected['dataItem'],
+ $instance->getDataItem()
+ );
+
+ $this->assertEquals(
+ $expected['property'],
+ $instance->getProperty()
+ );
+
+ $this->assertEquals(
+ $expected['queryString'],
+ $instance->getQueryString()
+ );
+
+ $this->assertEquals(
+ $expected['queryStringAsValue'],
+ $instance->getQueryString( true )
+ );
+
+ $this->assertEquals(
+ $expected['isSingleton'],
+ $instance->isSingleton()
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->getPrintRequests()
+ );
+
+ $this->assertEquals(
+ 1,
+ $instance->getSize()
+ );
+
+ $this->assertEquals(
+ 0,
+ $instance->getDepth()
+ );
+
+ $this->assertEquals(
+ 0,
+ $instance->getQueryFeatures()
+ );
+ }
+
+ /**
+ * @dataProvider comparativeHashProvider
+ */
+ public function testGetFingerprint( $description, $compareTo, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ $description->getFingerprint() === $compareTo->getFingerprint()
+ );
+ }
+
+ public function valueDescriptionProvider() {
+
+ $dataItem = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $provider[] = [
+ $dataItem,
+ null,
+ SMW_CMP_EQ,
+ [
+ 'comparator' => SMW_CMP_EQ,
+ 'dataItem' => $dataItem,
+ 'property' => null,
+ 'queryString' => '[[:Foo]]',
+ 'queryStringAsValue' => 'Foo',
+ 'isSingleton' => true
+ ]
+ ];
+
+ $provider['page.1'] = [
+ $dataItem,
+ null,
+ SMW_CMP_LEQ,
+ [
+ 'comparator' => SMW_CMP_LEQ,
+ 'dataItem' => $dataItem,
+ 'property' => null,
+ 'queryString' => '[[≤Foo]]',
+ 'queryStringAsValue' => '≤Foo',
+ 'isSingleton' => false
+ ]
+ ];
+
+ $property = DIProperty::newFromUserLabel( 'Foo' )->setPropertyTypeId( '_num' );
+ $dataItem = new DINumber( 9001 );
+
+ $provider['num.1'] = [
+ $dataItem,
+ $property,
+ SMW_CMP_LEQ,
+ [
+ 'comparator' => SMW_CMP_LEQ,
+ 'dataItem' => $dataItem,
+ 'property' => $property,
+ 'queryString' => '[[≤9001]]',
+ 'queryStringAsValue' => '≤9001',
+ 'isSingleton' => false
+ ]
+ ];
+
+ $property = DIProperty::newFromUserLabel( 'Foo' )->setPropertyTypeId( '_num' );
+ $dataItem = new DINumber( 9001.356 );
+
+ $provider['num.2'] = [
+ $dataItem,
+ $property,
+ SMW_CMP_GEQ,
+ [
+ 'comparator' => SMW_CMP_GEQ,
+ 'dataItem' => $dataItem,
+ 'property' => $property,
+ 'queryString' => '[[≥9001.356]]',
+ 'queryStringAsValue' => '≥9001.356',
+ 'isSingleton' => false
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function comparativeHashProvider() {
+
+ $provider[] = [
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_EQ
+ ),
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_EQ
+ ),
+ true
+ ];
+
+ $provider[] = [
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_EQ
+ ),
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_LEQ
+ ),
+ false
+ ];
+
+ $provider[] = [
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_EQ
+ ),
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), new DIProperty( 'Bar' ), SMW_CMP_EQ
+ ),
+ false
+ ];
+
+ // Inverse case
+ $provider[] = [
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), new DIProperty( 'Bar', true ), SMW_CMP_EQ
+ ),
+ new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ), new DIProperty( 'Bar' ), SMW_CMP_EQ
+ ),
+ false
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/DescriptionProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/DescriptionProcessorTest.php
new file mode 100644
index 00000000..0a1fcde5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/DescriptionProcessorTest.php
@@ -0,0 +1,258 @@
+<?php
+
+namespace SMW\Tests\Query\Parser;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Parser\DescriptionProcessor;
+
+/**
+ * @covers SMW\Query\Parser\DescriptionProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DescriptionProcessorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ DescriptionProcessor::class,
+ new DescriptionProcessor()
+ );
+ }
+
+ public function testError() {
+
+ $instance = new DescriptionProcessor();
+ $instance->addError( 'abc' );
+
+ $this->assertEquals(
+ [ '[2,"abc"]' ],
+ $instance->getErrors()
+ );
+
+ $instance->addErrorWithMsgKey( 'Foo' );
+
+ $this->assertCount(
+ 2,
+ $instance->getErrors()
+ );
+ }
+
+ public function testDescriptionForPropertyObjectValue() {
+
+ $instance = new DescriptionProcessor();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Description',
+ $instance->newDescriptionForPropertyObjectValue( new DIProperty( 'Foo' ), 'bar' )
+ );
+ }
+
+ public function testDescriptionForWikiPageValueChunkOnEqualMatch() {
+
+ $instance = new DescriptionProcessor();
+
+ $valueDescription = $instance->newDescriptionForWikiPageValueChunk( 'bar' );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ $valueDescription
+ );
+
+ $this->assertEquals(
+ new DIWikiPage( 'Bar', NS_MAIN ),
+ $valueDescription->getDataItem()
+ );
+ }
+
+ public function testnewDescriptionForWikiPageValueChunkOnApproximateValue() {
+
+ $instance = new DescriptionProcessor();
+
+ $valueDescription = $instance->newDescriptionForWikiPageValueChunk( '~bar' );
+
+ $this->assertEquals(
+ new DIWikiPage( 'bar', NS_MAIN ),
+ $valueDescription->getDataItem()
+ );
+ }
+
+ public function testGetDisjunctiveCompoundDescription() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = $instance->newDescriptionForWikiPageValueChunk( 'bar' );
+
+ $newDescription = $instance->newDescriptionForPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ 'foobar'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Disjunction',
+ $instance->asOr( $currentDescription, $newDescription )
+ );
+ }
+
+ public function testGetDisjunctiveCompoundDescriptionForCurrentConjunction() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = new Conjunction();
+
+ $newDescription = $instance->newDescriptionForPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ 'foobar'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Disjunction',
+ $instance->asOr( $currentDescription, $newDescription )
+ );
+ }
+
+ public function testGetDisjunctiveCompoundDescriptionForCurrentDisjunction() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = new Disjunction();
+
+ $newDescription = $instance->newDescriptionForPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ 'foobar'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Disjunction',
+ $instance->asOr( $currentDescription, $newDescription )
+ );
+ }
+
+ public function testTryToGetDisjunctiveCompoundDescriptionForNullNewDescription() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = $instance->newDescriptionForWikiPageValueChunk( 'bar' );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ $instance->asOr( $currentDescription, null )
+ );
+ }
+
+ public function testTryToGetDisjunctiveCompoundDescriptionForNullCurrentDescription() {
+
+ $instance = new DescriptionProcessor();
+
+ $newDescription = $instance->newDescriptionForWikiPageValueChunk( 'bar' );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ $instance->asOr( null, $newDescription )
+ );
+ }
+
+ public function testGetConjunctiveCompoundDescription() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = $instance->newDescriptionForWikiPageValueChunk( 'bar' );
+
+ $newDescription = $instance->newDescriptionForPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ 'foobar'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ $instance->asAnd( $currentDescription, $newDescription )
+ );
+ }
+
+ public function testGetConjunctiveCompoundDescriptionForCurrentConjunction() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = new Conjunction();
+
+ $newDescription = $instance->newDescriptionForPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ 'foobar'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ $instance->asAnd( $currentDescription, $newDescription )
+ );
+ }
+
+ public function testGetConjunctiveCompoundDescriptionForCurrentDisjunction() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = new Disjunction();
+
+ $newDescription = $instance->newDescriptionForPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ 'foobar'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ $instance->asAnd( $currentDescription, $newDescription )
+ );
+ }
+
+ public function testTryToGetConjunctiveCompoundDescriptionForNullNewDescription() {
+
+ $instance = new DescriptionProcessor();
+
+ $currentDescription = $instance->newDescriptionForWikiPageValueChunk( 'bar' );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ $instance->asAnd( $currentDescription, null )
+ );
+ }
+
+ public function testTryToGetConjunctiveCompoundDescriptionForNullCurrentDescription() {
+
+ $instance = new DescriptionProcessor();
+
+ $newDescription = $instance->newDescriptionForWikiPageValueChunk( 'bar' );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\ValueDescription',
+ $instance->asAnd( null, $newDescription )
+ );
+ }
+
+ public function testConstuctDescriptionWithContextPage() {
+
+ $instance = new DescriptionProcessor();
+
+ $instance->setContextPage(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $currentDescription = new Disjunction();
+
+ $newDescription = $instance->newDescriptionForPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ 'foobar'
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Language\Conjunction',
+ $instance->asAnd( $currentDescription, $newDescription )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/LegacyParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/LegacyParserTest.php
new file mode 100644
index 00000000..8d1344f5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/LegacyParserTest.php
@@ -0,0 +1,380 @@
+<?php
+
+namespace SMW\Tests\Query\Parser;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\DescriptionFactory;
+use SMW\Query\Parser\DescriptionProcessor;
+use SMW\Query\Parser\LegacyParser as QueryParser;
+use SMW\Query\Parser\Tokenizer;
+use SMW\Query\QueryToken;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Query\Parser\LegacyParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class LegacyParserTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $descriptionFactory;
+ private $queryParser;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->descriptionFactory = new DescriptionFactory();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->queryParser = new QueryParser(
+ new DescriptionProcessor(),
+ new Tokenizer(),
+ new QueryToken()
+ );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $descriptionProcessor = $this->getMockBuilder( '\SMW\Query\Parser\DescriptionProcessor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tokenizer = $this->getMockBuilder( '\SMW\Query\Parser\Tokenizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryToken = $this->getMockBuilder( '\SMW\Query\QueryToken' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // Legacy class match
+ $this->assertInstanceOf(
+ '\SMWQueryParser',
+ new QueryParser( $descriptionProcessor, $tokenizer, $queryToken )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Parser',
+ new QueryParser( $descriptionProcessor, $tokenizer, $queryToken )
+ );
+ }
+
+ public function testCreateCondition() {
+
+ $this->assertEquals(
+ '[[Foo::Bar]]',
+ $this->queryParser->createCondition( 'Foo', 'Bar' )
+ );
+
+ $this->assertEquals(
+ '[[Foo::Bar]]',
+ $this->queryParser->createCondition( new DIProperty( 'Foo' ), 'Bar' )
+ );
+ }
+
+ public function testPropertyWildardDescription() {
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Foo' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newThingDescription()
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Foo::+]]' )
+ );
+ }
+
+ public function testNamespaceWildardDescription() {
+
+ $description = $this->descriptionFactory->newNamespaceDescription(
+ NS_MAIN
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[:+]]' )
+ );
+ }
+
+ public function testPageDescription() {
+
+ $description = $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN, '' )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Foo]]' )
+ );
+ }
+
+ public function testPropertyNotEqualValueDescription() {
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Has foo' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'Has foo' )->setPropertyTypeId( '_wpg' ),
+ SMW_CMP_NEQ
+ )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Has foo::!Bar]]' )
+ );
+ }
+
+ public function testInversePropertyDescription() {
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Has foo', true )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'Has foo', true )->setPropertyTypeId( '_wpg' ),
+ SMW_CMP_EQ
+ )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[-Has foo::Bar]]' )
+ );
+ }
+
+ public function testConjunctionForCategoryPropertyValueGreaterThanOrEqualLessThanOrEqual() {
+
+ $someGreaterThanOrEqualProperty = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'One' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'A', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'One' )->setPropertyTypeId( '_wpg' ), SMW_CMP_GEQ )
+ );
+
+ $someLessThanOrEqualProperty = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'D', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ), SMW_CMP_LEQ )
+ );
+
+ $classDescription = $this->descriptionFactory->newClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY, '' )
+ );
+
+ $description = $this->descriptionFactory->newConjunction();
+ $description->addDescription( $classDescription );
+ $description->addDescription( $someGreaterThanOrEqualProperty );
+ $description->addDescription( $someLessThanOrEqualProperty );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:Foo]] [[One::>A]] [[Two::<D]]' )
+ );
+ }
+
+ public function testConjunctionForCategoryPropertyChainDescription() {
+
+ $someProperty = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'One' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ), SMW_CMP_EQ
+ )
+ )
+ );
+
+ $classDescription = $this->descriptionFactory->newClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY, '' )
+ );
+
+ $description = $this->descriptionFactory->newConjunction();
+ $description->addDescription( $classDescription );
+ $description->addDescription( $someProperty );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:Foo]] [[One.Two::Bar]]' )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:Foo]] [[One::<q>[[Two::Bar]]</q>]]' )
+ );
+ }
+
+ public function testDisjunctionForCategoryPropertyChainDescription() {
+
+ $someProperty = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'One' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ), SMW_CMP_EQ
+ )
+ )
+ );
+
+ $classDescription = $this->descriptionFactory->newClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY, '' )
+ );
+
+ $description = $this->descriptionFactory->newDisjunction();
+ $description->addDescription( $classDescription );
+ $description->addDescription( $someProperty );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:Foo]] OR [[One.Two::Bar]]' )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:Foo]] OR [[One::<q>[[Two::Bar]]</q>]]' )
+ );
+ }
+
+ public function testDisjunctionForCategoryChainDescription() {
+
+ $classFooDescription = $this->descriptionFactory->newClassDescription(
+ new DIWikiPage( 'Foo', NS_CATEGORY, '' )
+ );
+
+ $classBarDescription = $this->descriptionFactory->newClassDescription(
+ new DIWikiPage( 'Bar', NS_CATEGORY, '' )
+ );
+
+ $description = $this->descriptionFactory->newDisjunction();
+ $description->addDescription( $classFooDescription );
+ $description->addDescription( $classBarDescription );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:Foo||Bar]]' )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[Category:Foo]] OR [[Category:Bar]]' )
+ );
+ }
+
+ public function testCombinedSubobjectPropertyChainDescription() {
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'One' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( '_SOBJ' )->setPropertyTypeId( '__sob' ),
+ $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'Bar', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'Two' )->setPropertyTypeId( '_wpg' ), SMW_CMP_EQ
+ )
+ )
+ )
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[One.Has subobject.Two::Bar]]' )
+ );
+ }
+
+ public function testSubqueryDisjunction() {
+
+ $property = new DIProperty( 'HasSomeProperty' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $disjunction = $this->descriptionFactory->newDisjunction( [
+ $this->descriptionFactory->newValueDescription( new DIWikiPage( 'Foo', NS_MAIN ), $property ),
+ $this->descriptionFactory->newValueDescription( new DIWikiPage( 'Bar', NS_MAIN ), $property )
+ ] );
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ $property,
+ $disjunction
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[HasSomeProperty::Foo||Bar]]' )
+ );
+ }
+
+ public function testNestedPropertyConjunction() {
+
+ $property = DIProperty::newFromUserLabel( 'Born in' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $conjunction = $this->descriptionFactory->newConjunction( [
+ $this->descriptionFactory->newClassDescription( new DIWikiPage( 'City', NS_CATEGORY ) ),
+ $this->descriptionFactory->newSomeProperty(
+ DIProperty::newFromUserLabel( 'Located in' )->setPropertyTypeId( '_wpg' ),
+ $this->descriptionFactory->newValueDescription(
+ new DIWikiPage( 'Outback', NS_MAIN ),
+ DIProperty::newFromUserLabel( 'Located in' )->setPropertyTypeId( '_wpg' ) )
+ )
+ ]
+ );
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ $property,
+ $conjunction
+ );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '[[born in::<q>[[Category:City]] [[located in::Outback]]</q>]]' )
+ );
+ }
+
+ public function testRestrictedDefaultNamespace() {
+
+ $property = DIProperty::newFromUserLabel( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ $property,
+ $this->descriptionFactory->newValueDescription( new DIWikiPage( 'Bar', NS_MAIN ), $property )
+ );
+
+ $description = $this->descriptionFactory->newConjunction( [
+ $description,
+ $this->descriptionFactory->newNamespaceDescription( NS_MAIN )
+ ] );
+
+ $this->queryParser->setDefaultNamespaces( [ NS_MAIN ] );
+
+ $this->assertEquals(
+ $description,
+ $this->queryParser->getQueryDescription( '<q>[[Foo::Bar]]</q>[[:+]]' )
+ );
+
+ $this->assertEmpty(
+ $this->queryParser->getErrors()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TermParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TermParserTest.php
new file mode 100644
index 00000000..e7e705c1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TermParserTest.php
@@ -0,0 +1,219 @@
+<?php
+
+namespace SMW\Tests\Query\Parser;
+
+use SMW\Query\Parser\TermParser;
+
+/**
+ * @covers \SMW\Query\Parser\TermParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TermParserTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TermParser::class,
+ new TermParser()
+ );
+ }
+
+ /**
+ * @dataProvider termProvider
+ */
+ public function testTerm_parser( $term, $expected ) {
+
+ $instance = new TermParser();
+
+ $this->assertEquals(
+ $expected,
+ $instance->parse( $term )
+ );
+ }
+
+ /**
+ * @dataProvider term_prefixProvider
+ */
+ public function testTerm_prefix_parser( $term, $prefixes, $expected ) {
+
+ $instance = new TermParser( $prefixes );
+
+ $this->assertEquals(
+ $expected,
+ $instance->parse( $term )
+ );
+ }
+
+ public function termProvider() {
+
+ yield [
+ 'in:foo',
+ '[[in:foo]]'
+ ];
+
+ yield [
+ '[[in:foo]]',
+ '[[in:foo]]'
+ ];
+
+ yield [
+ 'in:foo || bar',
+ '[[in:foo]] || bar'
+ ];
+
+ yield [
+ 'in:foo && bar',
+ '[[in:foo]] && bar'
+ ];
+
+ yield [
+ 'in:foo || in:bar',
+ '[[in:foo]] || [[in:bar]]'
+ ];
+
+ yield [
+ 'in:foo && in:bar',
+ '[[in:foo]] && [[in:bar]]'
+ ];
+
+ yield [
+ 'in:foo bar in:bar ',
+ '[[in:foo bar]] [[in:bar]]'
+ ];
+
+ yield [
+ 'in:foo bar && in:bar',
+ '[[in:foo bar]] && [[in:bar]]'
+ ];
+
+ yield [
+ 'in:foo bar || in:bar ',
+ '[[in:foo bar]] || [[in:bar]]'
+ ];
+
+ yield [
+ '(in:foo bar && in:foo) || in:bar ',
+ '<q>[[in:foo bar]] && [[in:foo]]</q> || [[in:bar]]'
+ ];
+
+ yield [
+ 'in:foo bar in:bar phrase:foobar 123 && in:oooo',
+ '[[in:foo bar]] [[in:bar]] [[phrase:foobar 123]] && [[in:oooo]]'
+ ];
+
+ yield [
+ '<q>in:foo bar && in:bar</q> OR phrase:foo bar foobar',
+ '<q>[[in:foo bar]] && [[in:bar]]</q> OR [[phrase:foo bar foobar]]'
+ ];
+
+ yield [
+ '(in:foo && in:bar)||in:foobar',
+ '<q>[[in:foo]] && [[in:bar]]</q> || [[in:foobar]]'
+ ];
+
+ yield [
+ '(in:foo && (in:bar AND not:ooo)) || in:foobar',
+ '<q>[[in:foo]] && <q>[[in:bar]] AND [[not:ooo]]</q></q> || [[in:foobar]]'
+ ];
+
+ yield [
+ '<q>in:foo bar && in:bar</q> OR [[Has number::123]]',
+ '<q>[[in:foo bar]] && [[in:bar]]</q> OR [[Has number::123]]'
+ ];
+
+ yield [
+ 'in:foo [[Has foo::bar]]',
+ '[[in:foo]] [[Has foo::bar]]'
+ ];
+
+ yield [
+ 'in:foo [[Has foo::bar]] (in:foo bar)',
+ '[[in:foo]] [[Has foo::bar]] <q>[[in:foo bar]]</q>'
+ ];
+
+ yield [
+ 'category:foo',
+ '[[category:foo]]'
+ ];
+
+ yield [
+ 'foo',
+ 'foo'
+ ];
+
+ yield [
+ '<q>[[Bar property::Foobar]]</q> Foo',
+ '<q>[[Bar property::Foobar]]</q> Foo'
+ ];
+
+ yield [
+ 'in:foo [[Has foo::bar]] (in:(foo bar && fin))',
+ '[[in:foo]] [[Has foo::bar]] <q>[[in:foo bar]] && [[in:fin]]</q>'
+ ];
+
+ yield [
+ 'has:foo has:bar',
+ '[[foo::+]] [[bar::+]]'
+ ];
+
+ yield [
+ 'has:(foo && bar)',
+ '[[foo::+]] && [[bar::+]]'
+ ];
+
+ yield [
+ 'in:(foo && bar) in:(ham && cheese)',
+ '[[in:foo]] && [[in:bar]] [[in:ham]] && [[in:cheese]]'
+ ];
+
+ yield [
+ 'has:(foo && bar) in:(ham && cheese)',
+ '[[foo::+]] && [[bar::+]] [[in:ham]] && [[in:cheese]]'
+ ];
+ }
+
+ public function term_prefixProvider() {
+
+ yield [
+ 'in:foo || not:bar',
+ [ 'keyw' => [ 'Has keyword', 'Keyw' ] ],
+ '[[in:foo]] || [[not:bar]]'
+ ];
+
+ yield [
+ 'in:foo || keyword:foo bar || keyw:foo bar',
+ [ 'keyw' => [ 'Has keyword', 'Keyw' ] ],
+ '[[in:foo]] || keyword:foo bar]] || <q>[[Has keyword::foo bar]] || [[Keyw::foo bar]]</q>'
+ ];
+
+ yield [
+ 'in:foo keyw:foo bar',
+ [ 'keyw' => [ 'Has keyword', 'Keyw' ] ],
+ '[[in:foo]] <q>[[Has keyword::foo bar]] || [[Keyw::foo bar]]</q>'
+ ];
+
+ yield [
+ 'in:foo keyw:foo bar [[Foo::bar]]',
+ [ 'keyw' => [ 'Has keyword', 'Keyw' ] ],
+ '[[in:foo]] <q>[[Has keyword::foo bar]] || [[Keyw::foo bar]]</q> [[Foo::bar]]'
+ ];
+
+ yield [
+ 'in:foo (a:foo bar || not:bar)',
+ [ 'a' => [ 'Has keyword', 'Keyw' ] ],
+ '[[in:foo]] <q><q>[[Has keyword::foo bar]] || [[Keyw::foo bar]]</q> || [[not:bar]]</q>'
+ ];
+
+ yield [
+ 'in:foo',
+ [ 'in' => [ 'a', 'b' ] ],
+ '[[in:foo]]'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TokenizerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TokenizerTest.php
new file mode 100644
index 00000000..6c509426
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Parser/TokenizerTest.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace SMW\Tests\Query\Parser;
+
+use SMW\Query\Parser\Tokenizer;
+
+/**
+ * @covers \SMW\Query\Parser\Tokenizer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TokenizerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Tokenizer::class,
+ new Tokenizer()
+ );
+ }
+
+ /**
+ * @dataProvider tokenProvider
+ */
+ public function testGetToken( $currentString, $stoppattern, $expectedRes, $expectedCurrent ) {
+
+ $instance = new Tokenizer();
+ $instance->setDefaultPattern( [] );
+
+ $res = $instance->getToken( $currentString, $stoppattern );
+
+ $this->assertEquals(
+ $expectedRes,
+ $res
+ );
+
+ $this->assertEquals(
+ $expectedCurrent,
+ $currentString
+ );
+ }
+
+ public function tokenProvider() {
+
+ yield [
+ '',
+ '',
+ '',
+ ''
+ ];
+
+ yield [
+ '[[Foo]]',
+ '',
+ '[[',
+ 'Foo]]'
+ ];
+
+ yield [
+ '|Foo',
+ '',
+ '|',
+ 'Foo'
+ ];
+
+ yield [
+ '::Foo',
+ '',
+ '::',
+ 'Foo'
+ ];
+
+ yield [
+ 'Foo]]',
+ '',
+ 'Foo',
+ ']]'
+ ];
+
+ yield [
+ 'Foo]][[Bar',
+ '',
+ 'Foo',
+ ']][[Bar'
+ ];
+
+ yield [
+ ']][[Bar',
+ '',
+ ']]',
+ '[[Bar'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/DeserializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/DeserializerTest.php
new file mode 100644
index 00000000..72c237d5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/DeserializerTest.php
@@ -0,0 +1,210 @@
+<?php
+
+namespace SMW\Tests\Query\PrintRequest;
+
+use SMW\DataValues\PropertyChainValue;
+use SMW\Localizer;
+use SMW\Query\PrintRequest;
+use SMW\Query\PrintRequest\Deserializer;
+use SMWPropertyValue as PropertyValue;
+
+/**
+ * @covers SMW\Query\PrintRequest\Deserializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DeserializerTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider textProvider
+ */
+ public function testDeserialize( $text, $showMode, $expectedLabel, $expectedMode, $expectedDataInstance, $expectedOutputFormat ) {
+
+ $instance = Deserializer::deserialize( $text, $showMode );
+
+ $this->assertEquals(
+ $expectedLabel,
+ $instance->getLabel()
+ );
+
+ $this->assertEquals(
+ $expectedMode,
+ $instance->getMode()
+ );
+
+ if ( $expectedDataInstance !== null ) {
+ $this->assertInstanceOf(
+ $expectedDataInstance,
+ $instance->getData()
+ );
+ }
+
+ $this->assertSame(
+ $expectedOutputFormat,
+ $instance->getOutputFormat()
+ );
+ }
+
+ public function textProvider() {
+
+ #0
+ $provider[] = [
+ 'Foo',
+ false,
+ 'Foo',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ ''
+ ];
+
+ #1
+ $provider[] = [
+ '-Foo',
+ false,
+ '-Foo',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ ''
+ ];
+
+ #2
+ $provider[] = [
+ '-Foo=Bar',
+ false,
+ 'Bar',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ ''
+ ];
+
+ #3
+ // Category
+ $categoryName = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+ $provider[] = [
+ 'Category',
+ false,
+ $categoryName,
+ PrintRequest::PRINT_CATS,
+ null,
+ ''
+ ];
+
+ #4
+ // Category
+ $provider[] = [
+ 'Categories',
+ false,
+ $categoryName,
+ PrintRequest::PRINT_CATS,
+ null,
+ ''
+ ];
+
+ #5
+ $provider[] = [
+ 'Bar#foobar',
+ false,
+ 'Bar',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ 'foobar'
+ ];
+
+ #6
+ $provider[] = [
+ 'Foo#',
+ false,
+ 'Foo',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ '-'
+ ];
+
+ #7, 1464
+ $provider[] = [
+ 'Has boolean#<span style="color: green; font-size: 120%;">&#10003;</span>,<span style="color: #AA0000; font-size: 120%;">&#10005;</span>=Label on (&#10003;,&#10005;)',
+ false,
+ 'Label on (&#10003;,&#10005;)',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ '<span style="color: green; font-size: 120%;">&#10003;</span>,<span style="color: #AA0000; font-size: 120%;">&#10005;</span>'
+ ];
+
+ #8
+ $provider[] = [
+ 'Foo.Bar',
+ false,
+ 'Bar',
+ PrintRequest::PRINT_CHAIN,
+ PropertyChainValue::class,
+ ''
+ ];
+
+ #9
+ $provider[] = [
+ 'Foo.Bar#foobar',
+ false,
+ 'Bar',
+ PrintRequest::PRINT_CHAIN,
+ PropertyChainValue::class,
+ 'foobar'
+ ];
+
+ #10 ...
+ $provider[] = [
+ 'Foo = <span style="color: green; font-size: 120%;">Label</span>',
+ false,
+ '<span style="color: green; font-size: 120%;">Label</span>',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ ''
+ ];
+
+ #11 ...
+ $provider[] = [
+ 'Foo#Bar = <span style="color: green; font-size: 120%;">Label</span>',
+ false,
+ '<span style="color: green; font-size: 120%;">Label</span>',
+ PrintRequest::PRINT_PROP,
+ PropertyValue::class,
+ 'Bar'
+ ];
+
+ #12 #481
+ $provider[] = [
+ '#=Foo',
+ false,
+ 'Foo',
+ PrintRequest::PRINT_THIS,
+ null,
+ ''
+ ];
+
+ #13 #481
+ $provider[] = [
+ '#=Foo#',
+ false,
+ 'Foo',
+ PrintRequest::PRINT_THIS,
+ null,
+ '-'
+ ];
+
+ #13 #481
+ $provider[] = [
+ '#=Foo#-',
+ false,
+ 'Foo',
+ PrintRequest::PRINT_THIS,
+ null,
+ '-'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/FormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/FormatterTest.php
new file mode 100644
index 00000000..77db21a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/FormatterTest.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SMW\Tests\Query\PrintRequest;
+
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\Query\PrintRequest;
+use SMW\Query\PrintRequest\Formatter;
+
+/**
+ * @covers SMW\Query\PrintRequest\Formatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FormatterTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider printRequestProvider
+ */
+ public function testFormat( $printRequest, $linker, $outputType, $expected ) {
+
+ $this->assertSame(
+ $expected,
+ Formatter::format( $printRequest, $linker, $outputType )
+ );
+ }
+
+ public function printRequestProvider() {
+
+ $provider['print-cats-wiki'] = [
+ new PrintRequest( PrintRequest::PRINT_CATS, 'Foo' ),
+ null,
+ Formatter::FORMAT_WIKI,
+ 'Foo'
+ ];
+
+ $provider['print-cats-html'] = [
+ new PrintRequest( PrintRequest::PRINT_CATS, 'Foo' ),
+ null,
+ Formatter::FORMAT_HTML,
+ 'Foo'
+ ];
+
+ $provider['print-ccat-html'] = [
+ new PrintRequest( PrintRequest::PRINT_CCAT, 'Foo', DIWikiPage::newFromText( 'Bar' )->getTitle() ),
+ null,
+ Formatter::FORMAT_HTML,
+ 'Foo'
+ ];
+
+ $provider['print-ccat-wiki'] = [
+ new PrintRequest( PrintRequest::PRINT_CCAT, 'Foo', DIWikiPage::newFromText( 'Bar' )->getTitle() ),
+ null,
+ Formatter::FORMAT_WIKI,
+ 'Foo'
+ ];
+
+ $provider['print-this-wiki'] = [
+ new PrintRequest( PrintRequest::PRINT_THIS, 'Foo' ),
+ null,
+ Formatter::FORMAT_WIKI,
+ 'Foo'
+ ];
+
+ $provider['print-this-html'] = [
+ new PrintRequest( PrintRequest::PRINT_THIS, 'Foo' ),
+ null,
+ Formatter::FORMAT_HTML,
+ 'Foo'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Bar' );
+
+ $provider['print-prop-wiki-no-linker'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, 'Foo', $data ),
+ null,
+ Formatter::FORMAT_WIKI,
+ 'Foo'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Bar' );
+
+ $provider['print-prop-html-no-linker'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, 'Foo', $data ),
+ null,
+ Formatter::FORMAT_HTML,
+ 'Foo'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/SerializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/SerializerTest.php
new file mode 100644
index 00000000..2149cd2e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequest/SerializerTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace SMW\Tests\Query\PrintRequest;
+
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\Query\PrintRequest;
+use SMW\Query\PrintRequest\Serializer;
+
+/**
+ * @covers SMW\Query\PrintRequest\Serializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SerializerTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider textProvider
+ */
+ public function testSerialize( $printRequest, $showParams, $expected ) {
+
+ $this->assertSame(
+ $expected,
+ Serializer::serialize( $printRequest, $showParams )
+ );
+ }
+
+ public function textProvider() {
+
+ $category = Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY );
+
+ $provider['print-cats'] = [
+ new PrintRequest( PrintRequest::PRINT_CATS, 'Foo' ),
+ false,
+ "?{$category}=Foo"
+ ];
+
+ $provider['print-ccat'] = [
+ new PrintRequest( PrintRequest::PRINT_CCAT, 'Foo', DIWikiPage::newFromText( 'Bar' )->getTitle() ),
+ false,
+ '?Bar=Foo'
+ ];
+
+ $provider['print-this'] = [
+ new PrintRequest( PrintRequest::PRINT_THIS, 'Foo' ),
+ false,
+ '?=Foo'
+ ];
+
+ $provider['print-this-plain'] = [
+ new PrintRequest( PrintRequest::PRINT_THIS, 'Foo', null, '-' ),
+ false,
+ '?=Foo#-'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Bar' );
+
+ $provider['print-prop'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, 'Foo', $data ),
+ false,
+ '?Bar#=Foo'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Bar' );
+
+ $provider['print-prop-output'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, 'Foo', $data, 'foobar' ),
+ false,
+ '?Bar#foobar=Foo'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Bar' );
+
+ $provider['print-prop-output-parameters-no-show'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, 'Foo', $data, 'foobar', [ 'index' => 2 ] ),
+ false,
+ '?Bar#foobar=Foo'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Bar' );
+
+ $provider['print-prop-output-parameters-show'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, 'Foo', $data, 'foobar', [ 'index' => 2 ] ),
+ true,
+ '?Bar#foobar=Foo|+index=2'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Modification date' );
+
+ $provider['predefined-property'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, '', $data ),
+ false,
+ '?Modification date#'
+ ];
+
+ $data = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Bar' );
+
+ $provider['print-prop-output-lang-index'] = [
+ new PrintRequest( PrintRequest::PRINT_PROP, 'Foo', $data, '', [ 'lang' => 'en', 'index' => '1' ] ),
+ true,
+ '?Bar=Foo|+lang=en'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestFactoryTest.php
new file mode 100644
index 00000000..4174bb97
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestFactoryTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\DIProperty;
+use SMW\Query\PrintRequest;
+use SMW\Query\PrintRequestFactory;
+
+/**
+ * @covers \SMW\Query\PrintRequestFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PrintRequestFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Query\PrintRequestFactory',
+ new PrintRequestFactory()
+ );
+ }
+
+ public function testCanConstructPrintRequestFromProperty() {
+
+ $instance = new PrintRequestFactory();
+
+ $printRequest = $instance->newFromProperty(
+ new DIProperty( 'Foo' )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\PrintRequest',
+ $printRequest
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $printRequest->getLabel()
+ );
+ }
+
+ public function testCanConstructPrintRequestFromText() {
+
+ $instance = new PrintRequestFactory();
+
+ $printRequest = $instance->newFromText(
+ 'Foo'
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\PrintRequest',
+ $printRequest
+ );
+ }
+
+ public function testPrintRequestFromTextToReturnNullOnInvalidText() {
+
+ $instance = new PrintRequestFactory();
+
+ $printRequest = $instance->newFromText(
+ '--[[Foo',
+ false
+ );
+
+ $this->assertNull(
+ $printRequest
+ );
+ }
+
+ public function testCanConstructThisPrintRequest() {
+
+ $instance = new PrintRequestFactory();
+
+ $printRequest = $instance->newThisPrintRequest(
+ 'Foo'
+ );
+
+ $this->assertTrue(
+ $printRequest->isMode( PrintRequest::PRINT_THIS )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestTest.php
new file mode 100644
index 00000000..8b986975
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/PrintRequestTest.php
@@ -0,0 +1,191 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\DIProperty;
+use SMW\Query\PrintRequest as PrintRequest;
+use SMWPropertyValue as PropertyValue;
+
+/**
+ * @covers SMW\Query\PrintRequest
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PrintRequestTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstructPropertyPrintRequest() {
+
+ $propertyValue = $this->getMockBuilder( '\SMWPropertyValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyValue->expects( $this->once() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $this->assertInstanceOf(
+ 'SMW\Query\PrintRequest',
+ new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue )
+ );
+ }
+
+ public function testSetLabel() {
+
+ $propertyValue = new PropertyValue( '__pro' );
+ $propertyValue->setDataItem( new DIProperty( 'Foo' ) );
+
+ $instance = new PrintRequest( PrintRequest::PRINT_PROP, null, $propertyValue );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getCanonicalLabel()
+ );
+
+ $this->assertEquals(
+ null,
+ $instance->getLabel()
+ );
+
+ $this->assertEquals(
+ null,
+ $instance->getWikiText()
+ );
+
+ $instance->setLabel( 'Bar' );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->getLabel()
+ );
+
+ $this->assertEquals(
+ 'Bar',
+ $instance->getWikiText()
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getCanonicalLabel()
+ );
+ }
+
+ /**
+ * @dataProvider textProvider
+ */
+ public function testFromText( $text, $showMode, $expectedLabel ) {
+
+ $instance = PrintRequest::newFromText( $text, $showMode );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\PrintRequest',
+ $instance
+ );
+
+ $this->assertEquals(
+ $expectedLabel,
+ $instance->getLabel()
+ );
+ }
+
+ public function testFromTextToReturnNullOnInvalidText() {
+
+ $instance = PrintRequest::newFromText( '--[[Foo' );
+
+ $this->assertNull(
+ $instance
+ );
+ }
+
+ public function testRemoveParameter() {
+
+ $instance = PrintRequest::newFromText( 'Foo' );
+ $instance->setParameter( 'foo', 123 );
+
+ $this->assertEquals(
+ [
+ 'foo' => 123
+ ],
+ $instance->getParameters()
+ );
+
+ $instance->removeParameter( 'foo' );
+
+ $this->assertEquals(
+ [],
+ $instance->getParameters()
+ );
+ }
+
+ public function textProvider() {
+
+ #0
+ $provider[] = [
+ 'Foo',
+ false,
+ 'Foo'
+ ];
+
+ #1
+ $provider[] = [
+ 'Foo',
+ true,
+ ''
+ ];
+
+ #2
+ $provider[] = [
+ 'Foo=Bar',
+ false,
+ 'Bar'
+ ];
+
+ #3
+ $provider[] = [
+ 'Foo=Bar#123',
+ false,
+ 'Bar#123'
+ ];
+
+ #4
+ $provider[] = [
+ 'Foo#123=Bar',
+ false,
+ 'Bar'
+ ];
+
+ #5
+ $provider[] = [
+ 'Category=Foo',
+ false,
+ 'Foo'
+ ];
+
+ #6
+ $provider[] = [
+ '-Foo',
+ false,
+ '-Foo'
+ ];
+
+ #7
+ $provider[] = [
+ '-Foo=Bar',
+ false,
+ 'Bar'
+ ];
+
+ #8, 1464
+ $provider[] = [
+ 'Has boolean#<span style="color: green; font-size: 120%;">&#10003;</span>,<span style="color: #AA0000; font-size: 120%;">&#10005;</span>=Label on (&#10003;,&#10005;)',
+ false,
+ 'Label on (&#10003;,&#10005;)'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/DefaultParamDefinitionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/DefaultParamDefinitionTest.php
new file mode 100644
index 00000000..c89dc1bf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/DefaultParamDefinitionTest.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\Query\Processor;
+
+use SMW\Query\Processor\DefaultParamDefinition;
+
+/**
+ * @covers \SMW\Query\Processor\DefaultParamDefinition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DefaultParamDefinitionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ DefaultParamDefinition::class,
+ new DefaultParamDefinition()
+ );
+ }
+
+ public function testBuildParamDefinitions() {
+
+ $vars = [
+ 'smwgResultFormats' => [],
+ 'smwgResultAliases' => [],
+ 'smwgQuerySources' => [],
+ 'smwgQDefaultLimit' => 42,
+ 'smwgQUpperbound' => 100
+ ];
+
+ $this->assertInternalType(
+ 'array',
+ DefaultParamDefinition::buildParamDefinitions( $vars )
+ );
+ }
+
+ public function testGetParamDefinitions() {
+
+ $this->assertInternalType(
+ 'array',
+ DefaultParamDefinition::getParamDefinitions()
+ );
+ }
+
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/ParamListProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/ParamListProcessorTest.php
new file mode 100644
index 00000000..4636db13
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/ParamListProcessorTest.php
@@ -0,0 +1,406 @@
+<?php
+
+namespace SMW\Tests\Query\Processor;
+
+use SMW\Query\Processor\ParamListProcessor;
+
+/**
+ * @covers \SMW\Query\Processor\ParamListProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ParamListProcessorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $printRequestFactory = $this->getMockBuilder( '\SMW\Query\PrintRequestFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ParamListProcessor::class,
+ new ParamListProcessor( $printRequestFactory )
+ );
+ }
+
+ /**
+ * @dataProvider parametersProvider
+ */
+ public function testPreprocess( $parameters, $showMode, $expected ) {
+
+ $printRequestFactory = $this->getMockBuilder( '\SMW\Query\PrintRequestFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ParamListProcessor(
+ $printRequestFactory
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->preprocess( $parameters, $showMode )
+ );
+ }
+
+ /**
+ * @dataProvider legacyParametersProvider
+ */
+ public function testLegacyArray( $parameters ) {
+
+ $printRequestFactory = $this->getMockBuilder( '\SMW\Query\PrintRequestFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ParamListProcessor(
+ $printRequestFactory
+ );
+
+ $a = $instance->format(
+ $parameters,
+ ParamListProcessor::FORMAT_LEGACY
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $a[0]
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $a[1]
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $a[2]
+ );
+ }
+
+ public function parametersProvider() {
+
+ yield [
+ [ '[[Foo::Bar]]' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ // #640
+ yield [
+ [ '[[Foo::Bar=Foobar]]' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar=Foobar]]',
+ 'printouts' => [],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ '[[Foo::&lt;Bar=Foobar&gt;]]' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::<Bar=Foobar>]]',
+ 'printouts' => [],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ // #3560
+ yield [
+ [ '[[Foo::Bar=-3DFoo]]' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar=-3DFoo]]',
+ 'printouts' => [],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ '[[Foo::Bar=-3DFoox003D]]' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar=-3DFoox003D]]',
+ 'printouts' => [],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ // A user shouldn't use `0x003D` as representation for `=`
+ yield [
+ [ '[[Foo::Bar=-3DFoo0x003D]]' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar=-3DFoo=]]',
+ 'printouts' => [],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ '[[Foo::Bar]]', 'mainlabel=-' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [],
+ 'parameters' => [
+ 'mainlabel' => '-'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ '[[Foo::Bar]]', '?Foobar' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [
+ '0bfab051cd82c364058617af13e9874a' => [
+ 'label' => 'Foobar',
+ 'params' => []
+ ]
+ ],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ '[[Foo::Bar]]', '?Foobar', '+abc=123' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [
+ '0bfab051cd82c364058617af13e9874a' => [
+ 'label' => 'Foobar',
+ 'params' => [
+ 'abc' => '123'
+ ]
+ ]
+ ],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ '[[Foo::Bar]]', '?Foobar', '+abc=123', '+abc=123' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [
+ '0bfab051cd82c364058617af13e9874a' => [
+ 'label' => 'Foobar',
+ 'params' => [
+ 'abc' => '123'
+ ]
+ ]
+ ],
+ 'parameters' => [],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ '[[Foo::Bar]]', '?Foobar', '+abc=123', '?ABC', '+abc=456', '+abc=+FOO', 'limit=10' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [
+ '0bfab051cd82c364058617af13e9874a' => [
+ 'label' => 'Foobar',
+ 'params' => [
+ 'abc' => '123'
+ ]
+ ],
+ '2a30f08efdf827f7e76b895fde0fe670' => [
+ 'label' => 'ABC',
+ 'params' => [
+ 'abc' => '456',
+ 'abc' => '+FOO'
+ ]
+ ]
+ ],
+ 'parameters' => [
+ 'limit' => '10'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ // mainlabel=Foo|+abc=123 is currently NOT supported
+ yield [
+ [ '[[Foo::Bar]]', 'mainlabel=Foo', '+abc=123' ],
+ false,
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [],
+ 'parameters' => [
+ 'mainlabel' => 'Foo'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ // #1645
+ yield [
+ [ 'Foo=Bar', 'link=none' ],
+ true,
+ [
+ 'showMode' => true,
+ 'templateArgs' => false,
+ 'query' => '[[:Foo=Bar]]',
+ 'printouts' => [],
+ 'parameters' => [
+ 'link' => 'none'
+ ],
+ 'this' => []
+ ]
+ ];
+
+
+ // #3196
+ yield [
+ [ 'Foo=Bar', 'link=none', 'intro=[[File:Foo.png|link=Bar]]' ],
+ true,
+ [
+ 'showMode' => true,
+ 'templateArgs' => false,
+ 'query' => '[[:Foo=Bar]]',
+ 'printouts' => [],
+ 'parameters' => [
+ 'link' => 'none',
+ 'intro' => '[[File:Foo.png|link=Bar]]'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [ 'Foo=Bar', 'link=none', '?ABC' ],
+ true,
+ [
+ 'showMode' => true,
+ 'templateArgs' => false,
+ 'query' => '[[:Foo=Bar]]',
+ 'printouts' => [
+ 'df76b46d65f71fd1a36054ec00947665' => [
+ 'label' => 'ABC',
+ 'params' => []
+ ]
+ ],
+ 'parameters' => [
+ 'link' => 'none'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ // #502
+ yield [
+ [ 'Foo=Bar', 'link=none', 'template=test', '?ABC' ],
+ true,
+ [
+ 'showMode' => true,
+ 'templateArgs' => true,
+ 'query' => '[[:Foo=Bar]]',
+ 'printouts' => [
+ '2a30f08efdf827f7e76b895fde0fe670' => [
+ 'label' => 'ABC',
+ 'params' => []
+ ]
+ ],
+ 'parameters' => [
+ 'link' => 'none',
+ 'template' => 'test'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ }
+
+ public function legacyParametersProvider() {
+
+ yield [
+ [
+ 'showMode' => false,
+ 'templateArgs' => false,
+ 'query' => '[[Foo::Bar]]',
+ 'printouts' => [
+ '0bfab051cd82c364058617af13e9874a' => [
+ 'label' => 'Foobar',
+ 'params' => [
+ 'abc' => '123'
+ ]
+ ],
+ '2a30f08efdf827f7e76b895fde0fe670' => [
+ 'label' => 'ABC',
+ 'params' => [
+ 'abc' => '456',
+ 'abc' => '+FOO'
+ ]
+ ]
+ ],
+ 'parameters' => [
+ 'limit' => '10'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ yield [
+ [
+ 'showMode' => true,
+ 'templateArgs' => false,
+ 'query' => '[[:Foo=Bar]]',
+ 'printouts' => [],
+ 'parameters' => [
+ 'link' => 'none'
+ ],
+ 'this' => []
+ ]
+ ];
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/QueryCreatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/QueryCreatorTest.php
new file mode 100644
index 00000000..73ea3063
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Processor/QueryCreatorTest.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace SMW\Tests\Query\Processor;
+
+use SMW\ApplicationFactory;
+use SMW\Query\Processor\QueryCreator;
+
+/**
+ * @covers SMW\Query\Processor\QueryCreator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QueryCreatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $queryFactory = $this->getMockBuilder( '\SMW\QueryFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ QueryCreator::class,
+ new QueryCreator( $queryFactory )
+ );
+ }
+
+ /**
+ * @dataProvider queryStringProvider
+ */
+ public function testCreate( $queryString, $params, $expected ) {
+
+ $instance = new QueryCreator(
+ ApplicationFactory::getInstance()->getQueryFactory()
+ );
+
+ $query = $instance->create( $queryString, $params );
+
+ $this->assertInstanceOf(
+ '\SMWQuery',
+ $query
+ );
+
+ $this->assertSame(
+ $expected,
+ $query->toString()
+ );
+ }
+
+ public function queryStringProvider() {
+
+ $provider[] = [
+ '[[Foo::Bar]]',
+ [
+ 'limit' => 42,
+ 'offset' => 12
+ ],
+ '[[Foo::Bar]]|limit=42|offset=12|mainlabel='
+ ];
+
+ $provider[] = [
+ '[[Foo::Bar]]',
+ [
+ 'source' => 'foobar',
+ 'mainLabel' => 'Some'
+ ],
+ '[[Foo::Bar]]|limit=50|offset=0|mainlabel=Some|source=foobar'
+ ];
+
+ $provider[] = [
+ '[[Foo::Bar]]',
+ [
+ 'sort' => [ '', 'SomeA', 'SomeB' ],
+ 'order' => [ 'desc', 'random', 'asc' ]
+ ],
+ '[[Foo::Bar]]|limit=50|offset=0|mainlabel=|sort=SomeA,SomeB|order=random,asc'
+ ];
+
+ $provider[] = [
+ '[[Foo::Bar]]',
+ [
+ 'sort' => [ ',' ]
+ ],
+ '[[Foo::Bar]]|limit=50|offset=0|mainlabel=|sort=,|order=asc'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotatorFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotatorFactoryTest.php
new file mode 100644
index 00000000..dcb030e4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotatorFactoryTest.php
@@ -0,0 +1,229 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotatorFactory;
+use SMWQuery as Query;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotatorFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ProfileAnnotatorFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotatorFactory',
+ new ProfileAnnotatorFactory()
+ );
+ }
+
+ public function testConstructDescriptionProfileAnnotator() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $instance = new ProfileAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\DescriptionProfileAnnotator',
+ $instance->newDescriptionProfileAnnotator( $query )
+ );
+ }
+
+ public function testConstructCombinedProfileAnnotator() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $instance = new ProfileAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotator',
+ $instance->newProfileAnnotator( $query, '' )
+ );
+ }
+
+ public function testConstructProfileAnnotatorsWithSourceAnnotator() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getQuerySource' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new ProfileAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\SourceProfileAnnotator',
+ $instance->newProfileAnnotator( $query, 'SomeFormat' )
+ );
+ }
+
+ public function testConstructProfileAnnotatorsWithDurationAnnotator() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $query->expects( $this->at( 4 ) )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( Query::PROC_QUERY_TIME ) )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new ProfileAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\DurationProfileAnnotator',
+ $instance->newProfileAnnotator( $query, 'SomeFormat' )
+ );
+ }
+
+ public function testConstructProfileAnnotatorsWithStatCodeAnnotator() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $query->expects( $this->at( 6 ) )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( Query::PROC_STATUS_CODE ) )
+ ->will( $this->returnValue( [ 100 ] ) );
+
+ $instance = new ProfileAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\StatusCodeProfileAnnotator',
+ $instance->newProfileAnnotator( $query, 'SomeFormat' )
+ );
+ }
+
+ public function testConstructCombinedProfileAnnotatorOnNullContextPage() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( null ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $instance = new ProfileAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotator',
+ $instance->newProfileAnnotator( $query, '' )
+ );
+ }
+
+ public function testConstructProfileAnnotators_SchemaLink() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $query->expects( $this->at( 7 ) )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( 'schema_link' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new ProfileAnnotatorFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\SchemaLinkProfileAnnotator',
+ $instance->newProfileAnnotator( $query, 'SomeFormat' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DescriptionProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DescriptionProfileAnnotatorTest.php
new file mode 100644
index 00000000..74ccdd27
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DescriptionProfileAnnotatorTest.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\DescriptionProfileAnnotator;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\DescriptionProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DescriptionProfileTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\DescriptionProfileAnnotator',
+ new DescriptionProfileAnnotator( $profileAnnotator, $description )
+ );
+ }
+
+ public function testCreateProfile() {
+
+ $subject =new DIWikiPage( __METHOD__, NS_MAIN, '', 'foo' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->once() )
+ ->method( 'getQueryString' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $description->expects( $this->once() )
+ ->method( 'getSize' )
+ ->will( $this->returnValue( 2 ) );
+
+ $description->expects( $this->once() )
+ ->method( 'getDepth' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new DescriptionProfileAnnotator(
+ new NullProfileAnnotator( $container ),
+ $description
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 3,
+ 'propertyKeys' => [ '_ASKST', '_ASKSI', '_ASKDE' ],
+ 'propertyValues' => [ 'Foo', 2, 42 ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getContainer()->getSemanticData()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DurationProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DurationProfileAnnotatorTest.php
new file mode 100644
index 00000000..259d0122
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/DurationProfileAnnotatorTest.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\DurationProfileAnnotator;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\DurationProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DurationProfileAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\DurationProfileAnnotator',
+ new DurationProfileAnnotator( $profileAnnotator, 0.42 )
+ );
+ }
+
+ /**
+ * @dataProvider durationDataProvider
+ */
+ public function testCreateProfile( $duration, $expected ) {
+
+ $subject =new DIWikiPage( __METHOD__, NS_MAIN, '', 'foo' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $instance = new DurationProfileAnnotator(
+ new NullProfileAnnotator( $container ),
+ $duration
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getContainer()->getSemanticData()
+ );
+ }
+
+ public function durationDataProvider() {
+
+ $provider = [];
+
+ $provider[] = [ 0, [
+ 'propertyCount' => 0
+ ] ];
+
+ $provider[] = [ 0.9001, [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ASKDU' ],
+ 'propertyValues' => [ 0.9001 ]
+ ] ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/FormatProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/FormatProfileAnnotatorTest.php
new file mode 100644
index 00000000..a08f10b6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/FormatProfileAnnotatorTest.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\FormatProfileAnnotator;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\FormatProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class FormatProfileAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\FormatProfileAnnotator',
+ new FormatProfileAnnotator( $profileAnnotator, 'table' )
+ );
+ }
+
+ public function testCreateProfile() {
+
+ $subject =new DIWikiPage( __METHOD__, NS_MAIN, '', 'foo' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $instance = new FormatProfileAnnotator(
+ new NullProfileAnnotator( $container ),
+ 'table'
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ASKFO' ],
+ 'propertyValues' => [ 'table' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getContainer()->getSemanticData()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/NullProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/NullProfileAnnotatorTest.php
new file mode 100644
index 00000000..e01bb766
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/NullProfileAnnotatorTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\NullProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class NullProfileAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $container = $this->getMockBuilder( '\SMWDIContainer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\NullProfileAnnotator',
+ new NullProfileAnnotator( $container )
+ );
+ }
+
+ public function testMethodAccess() {
+
+ $subject =new DIWikiPage( __METHOD__, NS_MAIN, '', '_QUERYadcb944aa33b2c972470b73964c547c0' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $instance = new NullProfileAnnotator(
+ $container
+ );
+
+ $instance->addAnnotation();
+
+ $this->assertInstanceOf(
+ '\SMW\DIProperty',
+ $instance->getProperty()
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $instance->getContainer()
+ );
+
+ $this->assertInstanceOf(
+ '\SMWContainerSemanticData',
+ $instance->getSemanticData()
+ );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/ParametersProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/ParametersProfileAnnotatorTest.php
new file mode 100644
index 00000000..00409cf9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/ParametersProfileAnnotatorTest.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMW\Query\ProfileAnnotators\ParametersProfileAnnotator;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\ParametersProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParametersProfileAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\ParametersProfileAnnotator',
+ new ParametersProfileAnnotator( $profileAnnotator, $query )
+ );
+ }
+
+ public function testCreateProfile() {
+
+ $subject =new DIWikiPage( __METHOD__, NS_MAIN, '', 'foo' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getOffset' )
+ ->will( $this->returnValue( 0 ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getQueryMode' )
+ ->will( $this->returnValue( 1 ) );
+
+ $instance = new ParametersProfileAnnotator(
+ new NullProfileAnnotator( $container ),
+ $query
+ );
+
+ $instance->addAnnotation();
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ASKPA' ],
+ 'propertyValues' => [ '{"limit":42,"offset":0,"sort":[],"order":[],"mode":1}' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getContainer()->getSemanticData()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SchemaLinkProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SchemaLinkProfileAnnotatorTest.php
new file mode 100644
index 00000000..89150c66
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SchemaLinkProfileAnnotatorTest.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMW\Query\ProfileAnnotators\SchemaLinkProfileAnnotator;
+use SMW\Tests\TestEnvironment;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\SchemaLinkProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SchemaLinkProfileAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = TestEnvironment::newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ SchemaLinkProfileAnnotator::class,
+ new SchemaLinkProfileAnnotator( $profileAnnotator, '' )
+ );
+ }
+
+ public function testAddAnnotationOnInvalidSchemaLinkTypeThrowsException() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SchemaLinkProfileAnnotator( $profileAnnotator, [] );
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->addAnnotation();
+ }
+
+ /**
+ * @dataProvider SchemaLinkProvider
+ */
+ public function testAddAnnotation( $SchemaLink, $expected ) {
+
+ $subject = new DIWikiPage( __METHOD__, NS_MAIN, '', '_QUERYe7d20a88999' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $instance = new SchemaLinkProfileAnnotator(
+ new NullProfileAnnotator( $container ),
+ $SchemaLink
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function SchemaLinkProvider() {
+
+ yield [
+ '',
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ yield [
+ 'Foo',
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_SCHEMA_LINK' ],
+ 'propertyValues' => [ 'Foo' ]
+ ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SourceProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SourceProfileAnnotatorTest.php
new file mode 100644
index 00000000..b88158ec
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/SourceProfileAnnotatorTest.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMW\Query\ProfileAnnotators\SourceProfileAnnotator;
+use SMW\Tests\TestEnvironment;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\SourceProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SourceProfileAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+ $this->semanticDataValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotators\SourceProfileAnnotator',
+ new SourceProfileAnnotator( $profileAnnotator )
+ );
+ }
+
+ /**
+ * @dataProvider sourceDataProvider
+ */
+ public function testCreateProfile( $source, $expected ) {
+
+ $subject = new DIWikiPage( __METHOD__, NS_MAIN, '', '_QUERYe7d20a88' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $instance = new SourceProfileAnnotator(
+ new NullProfileAnnotator( $container ),
+ $source
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function sourceDataProvider() {
+
+ $provider = [];
+
+ $provider[] = [ '', [
+ 'propertyCount' => 0
+ ] ];
+
+ $provider[] = [ 'foo', [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ASKSC' ],
+ 'propertyValues' => [ 'foo' ]
+ ] ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/StatusCodeProfileAnnotatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/StatusCodeProfileAnnotatorTest.php
new file mode 100644
index 00000000..c451abf3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ProfileAnnotators/StatusCodeProfileAnnotatorTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace SMW\Tests\Query\ProfileAnnotators;
+
+use SMW\DIWikiPage;
+use SMW\Query\ProfileAnnotators\NullProfileAnnotator;
+use SMW\Query\ProfileAnnotators\StatusCodeProfileAnnotator;
+use SMW\Tests\TestEnvironment;
+use SMWContainerSemanticData as ContainerSemanticData;
+use SMWDIContainer as DIContainer;
+
+/**
+ * @covers \SMW\Query\ProfileAnnotators\StatusCodeProfileAnnotator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class StatusCodeProfileAnnotatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = TestEnvironment::newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $profileAnnotator = $this->getMockBuilder( '\SMW\Query\ProfileAnnotator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ StatusCodeProfileAnnotator::class,
+ new StatusCodeProfileAnnotator( $profileAnnotator )
+ );
+ }
+
+ /**
+ * @dataProvider codesDataProvider
+ */
+ public function testCreateProfile( $codes, $expected ) {
+
+ $subject = new DIWikiPage( __METHOD__, NS_MAIN, '', '_QUERYe7d20a88' );
+
+ $container = new DIContainer(
+ new ContainerSemanticData( $subject )
+ );
+
+ $instance = new StatusCodeProfileAnnotator(
+ new NullProfileAnnotator( $container ),
+ $codes
+ );
+
+ $instance->addAnnotation();
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function codesDataProvider() {
+
+ $provider[] = [
+ [],
+ [
+ 'propertyCount' => 0
+ ]
+ ];
+
+ $provider[] = [
+ [ 100 ],
+ [
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ASKCO' ],
+ 'propertyValues' => [ 100 ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryComparatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryComparatorTest.php
new file mode 100644
index 00000000..fe1f1525
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryComparatorTest.php
@@ -0,0 +1,191 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\Query\QueryComparator;
+
+/**
+ * @covers \SMW\Query\QueryComparator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class QueryComparatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $comparatorList = '';
+
+ $this->assertInstanceOf(
+ '\SMW\Query\QueryComparator',
+ new QueryComparator( $comparatorList, false )
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Query\QueryComparator',
+ QueryComparator::getInstance()
+ );
+ }
+
+ /**
+ * @dataProvider stringComparatorProvider
+ */
+ public function testGetComparatorFromString( $stringComparator, $expected ) {
+
+ $comparatorList = '';
+
+ $instance = new QueryComparator( $comparatorList, false );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getComparatorFromString( $stringComparator )
+ );
+ }
+
+ /**
+ * @dataProvider stringComparatorProvider
+ */
+ public function testGetStringForComparator( $stringComparator, $comparator ) {
+
+ $comparatorList = '';
+
+ $instance = new QueryComparator( $comparatorList, false );
+
+ $this->assertEquals(
+ $stringComparator,
+ $instance->getStringForComparator( $comparator )
+ );
+ }
+
+ /**
+ * @dataProvider extractStringComparatorProvider
+ */
+ public function testExtractComparatorFromString( $string, $expectedString, $expectedComparator ) {
+
+ $comparatorList = '';
+
+ $instance = new QueryComparator( $comparatorList, true );
+
+ $this->assertEquals(
+ $expectedComparator,
+ $instance->extractComparatorFromString( $string )
+ );
+
+ $this->assertEquals(
+ $expectedString,
+ $string
+ );
+ }
+
+ /**
+ * @dataProvider containsComparatorProvider
+ */
+ public function testContainsComparator( $string, $comparator, $expected ) {
+
+ $comparatorList = '';
+
+ $instance = new QueryComparator( $comparatorList, true );
+
+ $this->assertEquals(
+ $expected,
+ $instance->containsComparator( $string, $comparator )
+ );
+ }
+
+ public function stringComparatorProvider() {
+
+ $provider[] = [
+ '!~',
+ SMW_CMP_NLKE
+ ];
+
+ return $provider;
+ }
+
+ public function extractStringComparatorProvider() {
+
+ $provider[] = [
+ '!~Foo',
+ 'Foo',
+ SMW_CMP_NLKE
+ ];
+
+ $provider[] = [
+ '<Foo',
+ 'Foo',
+ SMW_CMP_LESS
+ ];
+
+ $provider[] = [
+ 'like:Foo',
+ 'Foo',
+ SMW_CMP_PRIM_LIKE
+ ];
+
+ $provider[] = [
+ 'nlike:Foo',
+ 'Foo',
+ SMW_CMP_PRIM_NLKE
+ ];
+
+ return $provider;
+ }
+
+ public function containsComparatorProvider() {
+
+ $provider[] = [
+ '~someThing',
+ SMW_CMP_EQ,
+ false
+ ];
+
+ $provider[] = [
+ 'someThing',
+ SMW_CMP_EQ,
+ true
+ ];
+
+ $provider[] = [
+ '!~someThing',
+ SMW_CMP_NLKE,
+ true
+ ];
+
+ $provider[] = [
+ '!~someThing',
+ SMW_CMP_LIKE,
+ false
+ ];
+
+ $provider[] = [
+ '>>someThing',
+ SMW_CMP_LESS,
+ false
+ ];
+
+ $provider[] = [
+ '<<someThing',
+ SMW_CMP_LESS,
+ true
+ ];
+
+
+ $provider[] = [
+ 'like:someThing',
+ SMW_CMP_PRIM_LIKE,
+ true
+ ];
+
+ $provider[] = [
+ 'nlike:someThing',
+ SMW_CMP_PRIM_NLKE,
+ true
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryLinkerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryLinkerTest.php
new file mode 100644
index 00000000..64d34a54
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryLinkerTest.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\Query\QueryLinker;
+
+/**
+ * @covers SMW\Query\QueryLinker
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class QueryLinkerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\Query\QueryLinker',
+ new QueryLinker()
+ );
+ }
+
+ public function testGet() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getExtraPrintouts' )
+ ->will( $this->returnValue( [] ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getSortKeys' )
+ ->will( $this->returnValue( [] ) );
+
+ $parameters = [
+ 'Foo' => 'Bar',
+ 'Foobar'
+ ];
+
+ $this->assertInstanceOf(
+ 'SMWInfolink',
+ QueryLinker::get( $query, $parameters )
+ );
+ }
+
+ /**
+ * @dataProvider sortOrderProvider
+ */
+ public function testSort_PredefinedProperty( $sortKeys, $expected ) {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getExtraPrintouts' )
+ ->will( $this->returnValue( [] ) );
+
+ $query->expects( $this->once() )
+ ->method( 'getSortKeys' )
+ ->will( $this->returnValue( $sortKeys ) );
+
+ $link = QueryLinker::get( $query );
+ $link->setCompactLink( false );
+
+ $this->assertContains(
+ $expected,
+ $link->getLocalURL()
+ );
+ }
+
+ public function sortOrderProvider() {
+
+ yield[
+ [ '_MDAT' => 'DESC' ],
+ '&order=desc&sort=Modification%20date'
+ ];
+
+ yield[
+ [ '' => 'ASC' ],
+ '&mainlabel=&source=&offset='
+ ];
+
+ yield[
+ [ 'Foo_bar' => 'ASC' ],
+ '&mainlabel=&source=&offset=&order=asc&sort=Foo%20bar'
+ ];
+
+ yield[
+ [ '' => 'ASC', 'Foo_bar' => 'DESC' ],
+ '&mainlabel=&source=&offset=&order=asc%2Cdesc&sort=%2CFoo%20bar'
+ ];
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QuerySourceFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QuerySourceFactoryTest.php
new file mode 100644
index 00000000..43e567ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QuerySourceFactoryTest.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\Query\QuerySourceFactory;
+use SMW\QueryEngine;
+use SMW\Store;
+use SMW\StoreAware;
+use SMW\Tests\TestEnvironment;
+use SMWQuery as Query;
+
+/**
+ * @covers SMW\Query\QuerySourceFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QuerySourceFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ QuerySourceFactory::class,
+ new QuerySourceFactory( $this->store )
+ );
+ }
+
+ public function testGetFromFakeSource() {
+
+ $instance = new QuerySourceFactory(
+ $this->store,
+ [
+ 'foo' => FakeQueryEngine::class
+ ]
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\QueryEngine',
+ $instance->get( 'foo' )
+ );
+ }
+
+ public function testGetStandardStore() {
+
+ $instance = new QuerySourceFactory(
+ $this->store,
+ []
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\SQLStore',
+ $instance->get( 'sql_store' )
+ );
+
+ $this->assertEquals(
+ 'SMWSQLStore',
+ $instance->toString( 'sql_store' )
+ );
+ }
+
+ public function testGetAsString() {
+
+ $store = $this->getMockBuilder( '\SMW\SPARQLStore\SPARQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getInfo' )
+ ->will( $this->returnValue( [ 'SPARQLStore' ] ) );
+
+ $instance = new QuerySourceFactory(
+ $store,
+ []
+ );
+
+ $this->assertContains(
+ 'SPARQLStore',
+ $instance->toString()
+ );
+ }
+
+ public function testGetFromAnotherFakeSourceThatImplementsStoreAware() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->with( $this->stringContains( 'foo' ) );
+
+ $instance = new QuerySourceFactory(
+ $store,
+ [
+ 'bar' => AnotherFakeQueryEngine::class
+ ]
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\QueryEngine',
+ $instance->get( 'bar' )
+ );
+ }
+}
+
+class FakeQueryEngine implements QueryEngine {
+
+ public function getQueryResult( Query $query ) {
+ return '';
+ }
+
+}
+
+class AnotherFakeQueryEngine extends FakeQueryEngine implements StoreAware {
+
+ public function setStore( Store $store ) {
+ return $store->getConnection( 'foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryStringifierTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryStringifierTest.php
new file mode 100644
index 00000000..0156cfed
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryStringifierTest.php
@@ -0,0 +1,302 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\Query\QueryStringifier;
+
+/**
+ * @covers \SMW\Query\QueryStringifier
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QueryStringifierTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider queryProvider
+ */
+ public function testToArray( $query, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ QueryStringifier::toArray( $query )
+ );
+ }
+
+ /**
+ * @dataProvider queryProvider
+ */
+ public function testToJson( $query, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ json_decode( QueryStringifier::toJson( $query ), true )
+ );
+ }
+
+ /**
+ * @dataProvider queryProvider
+ */
+ public function testGet( $query, $array, $expected ) {
+
+ $this->assertSame(
+ $expected,
+ QueryStringifier::toString( $query )
+ );
+ }
+
+ /**
+ * @dataProvider queryProvider
+ */
+ public function testRawUrlEncode( $query, $array, $encode, $expected ) {
+
+ $this->assertSame(
+ $expected,
+ QueryStringifier::rawUrlEncode( $query )
+ );
+ }
+
+ public function queryProvider() {
+
+ #0
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryString' )
+ ->will( $this->returnValue( '[[Foo::bar]]' ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getOffset' )
+ ->will( $this->returnValue( 0 ) );
+
+ yield [
+ $query,
+ [
+ 'conditions' => '[[Foo::bar]]',
+ 'parameters' => [
+ 'limit' => 42,
+ 'offset' => 0,
+ 'mainlabel' => null
+ ],
+ 'printouts' => []
+ ],
+ '[[Foo::bar]]|limit=42|offset=0|mainlabel=',
+ '%5B%5BFoo%3A%3Abar%5D%5D%7Climit%3D42%7Coffset%3D0%7Cmainlabel%3D'
+ ];
+
+ #1
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryString' )
+ ->will( $this->returnValue( '[[Foo::bar]]' ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getQuerySource' )
+ ->will( $this->returnValue( 'Baz' ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getOffset' )
+ ->will( $this->returnValue( 0 ) );
+
+ yield [
+ $query,
+ [
+ 'conditions' => '[[Foo::bar]]',
+ 'parameters' => [
+ 'limit' => 42,
+ 'offset' => 0,
+ 'mainlabel' => null,
+ 'source' => 'Baz'
+ ],
+ 'printouts' => []
+ ],
+ '[[Foo::bar]]|limit=42|offset=0|mainlabel=|source=Baz',
+ '%5B%5BFoo%3A%3Abar%5D%5D%7Climit%3D42%7Coffset%3D0%7Cmainlabel%3D%7Csource%3DBaz'
+ ];
+
+ #2
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryString' )
+ ->will( $this->returnValue( '[[Foo::bar]]' ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getOffset' )
+ ->will( $this->returnValue( 0 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getSortKeys' )
+ ->will( $this->returnValue( [ 'Foobar' => 'DESC' ] ) );
+
+ yield [
+ $query,
+ [
+ 'conditions' => '[[Foo::bar]]',
+ 'parameters' => [
+ 'limit' => 42,
+ 'offset' => 0,
+ 'mainlabel' => null,
+ 'sort' => 'Foobar',
+ 'order' => 'desc'
+ ],
+ 'printouts' => []
+ ],
+ '[[Foo::bar]]|limit=42|offset=0|mainlabel=|sort=Foobar|order=desc',
+ '%5B%5BFoo%3A%3Abar%5D%5D%7Climit%3D42%7Coffset%3D0%7Cmainlabel%3D%7Csort%3DFoobar%7Corder%3Ddesc'
+ ];
+
+ #3
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryString' )
+ ->will( $this->returnValue( '[[Foo::bar]]' ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getOffset' )
+ ->will( $this->returnValue( 0 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getSortKeys' )
+ ->will( $this->returnValue( [ 'Foobar' => 'DESC', 'Foobaz' => 'ASC' ] ) );
+
+ yield [
+ $query,
+ [
+ 'conditions' => '[[Foo::bar]]',
+ 'parameters' => [
+ 'limit' => 42,
+ 'offset' => 0,
+ 'mainlabel' => null,
+ 'sort' => 'Foobar,Foobaz',
+ 'order' => 'desc,asc'
+ ],
+ 'printouts' => []
+ ],
+ '[[Foo::bar]]|limit=42|offset=0|mainlabel=|sort=Foobar,Foobaz|order=desc,asc',
+ '%5B%5BFoo%3A%3Abar%5D%5D%7Climit%3D42%7Coffset%3D0%7Cmainlabel%3D%7Csort%3DFoobar%2CFoobaz%7Corder%3Ddesc%2Casc'
+ ];
+
+ #4
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getSerialisation' )
+ ->will( $this->returnValue( '?ABC' ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryString' )
+ ->will( $this->returnValue( '[[Foo::bar]]' ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getOffset' )
+ ->will( $this->returnValue( 0 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getExtraPrintouts' )
+ ->will( $this->returnValue( [ $printRequest ] ) );
+
+ yield [
+ $query,
+ [
+ 'conditions' => '[[Foo::bar]]',
+ 'parameters' => [
+ 'limit' => 42,
+ 'offset' => 0,
+ 'mainlabel' => null
+ ],
+ 'printouts' => [
+ '?ABC'
+ ]
+ ],
+ '[[Foo::bar]]|?ABC|limit=42|offset=0|mainlabel=',
+ '%5B%5BFoo%3A%3Abar%5D%5D%7C%3FABC%7Climit%3D42%7Coffset%3D0%7Cmainlabel%3D'
+ ];
+
+ #5 (#show returns with an extra =)
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getSerialisation' )
+ ->will( $this->returnValue( '?ABC' ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getQueryString' )
+ ->will( $this->returnValue( '[[Foo::bar]]' ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getOffset' )
+ ->will( $this->returnValue( 0 ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getExtraPrintouts' )
+ ->will( $this->returnValue( [ $printRequest ] ) );
+
+ yield [
+ $query,
+ [
+ 'conditions' => '[[Foo::bar]]',
+ 'parameters' => [
+ 'limit' => 42,
+ 'offset' => 0,
+ 'mainlabel' => null
+ ],
+ 'printouts' => [
+ '?ABC'
+ ]
+ ],
+ '[[Foo::bar]]|?ABC|limit=42|offset=0|mainlabel=',
+ '%5B%5BFoo%3A%3Abar%5D%5D%7C%3FABC%7Climit%3D42%7Coffset%3D0%7Cmainlabel%3D'
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTest.php
new file mode 100644
index 00000000..04f34b3b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTest.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMWQuery as Query;
+
+/**
+ * @covers \SMWQuery
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class QueryTest extends \PHPUnit_Framework_TestCase {
+
+ private $smwgQMaxLimit;
+ private $smwgQMaxInlineLimit;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->smwgQMaxLimit = $GLOBALS['smwgQMaxLimit'];
+ $this->smwgQMaxInlineLimit = $GLOBALS['smwgQMaxInlineLimit'];
+ }
+
+ public function testCanConstruct() {
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $this->assertInstanceOf(
+ '\SMWQuery',
+ new Query( $description )
+ );
+ }
+
+ public function testSetGetLimitForLowerbound() {
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new Query( $description, Query::INLINE_QUERY );
+
+ $lowerboundLimit = 1;
+
+ $this->assertGreaterThan(
+ $lowerboundLimit,
+ $this->smwgQMaxLimit
+ );
+
+ $this->assertGreaterThan(
+ $lowerboundLimit,
+ $this->smwgQMaxInlineLimit
+ );
+
+ $instance->setLimit( $lowerboundLimit, true );
+
+ $this->assertEquals(
+ $lowerboundLimit,
+ $instance->getLimit()
+ );
+
+ $instance->setLimit( $lowerboundLimit, false );
+
+ $this->assertEquals(
+ $lowerboundLimit,
+ $instance->getLimit()
+ );
+ }
+
+ public function testSetGetLimitForUpperboundWhereLimitIsRestrictedByGLOBALRequirements() {
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new Query( $description, Query::INLINE_QUERY );
+
+ $upperboundLimit = 999999999;
+
+ $this->assertLessThan(
+ $upperboundLimit,
+ $this->smwgQMaxLimit
+ );
+
+ $this->assertLessThan(
+ $upperboundLimit,
+ $this->smwgQMaxInlineLimit
+ );
+
+ $instance->setLimit( $upperboundLimit, true );
+
+ $this->assertEquals(
+ $this->smwgQMaxInlineLimit,
+ $instance->getLimit()
+ );
+
+ $instance->setLimit( $upperboundLimit, false );
+
+ $this->assertEquals(
+ $this->smwgQMaxLimit,
+ $instance->getLimit()
+ );
+ }
+
+ public function testSetGetLimitForUpperboundWhereLimitIsUnrestricted() {
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new Query( $description, Query::INLINE_QUERY );
+
+ $upperboundLimit = 999999999;
+
+ $this->assertLessThan(
+ $upperboundLimit,
+ $this->smwgQMaxLimit
+ );
+
+ $this->assertLessThan(
+ $upperboundLimit,
+ $this->smwgQMaxInlineLimit
+ );
+
+ $instance->setUnboundLimit( $upperboundLimit );
+
+ $this->assertEquals(
+ $upperboundLimit,
+ $instance->getLimit()
+ );
+ }
+
+ public function testToArray() {
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $printRequest = $this->getMockBuilder( 'SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Query( $description, Query::INLINE_QUERY );
+ $instance->setExtraPrintouts( [ $printRequest ] );
+
+ $serialized = $instance->toArray();
+
+ $this->assertInternalType(
+ 'array',
+ $serialized
+ );
+
+ $expected = [
+ 'conditions',
+ 'parameters',
+ 'printouts'
+ ];
+
+ foreach ( $expected as $key ) {
+ $this->assertArrayHasKey( $key, $serialized );
+ }
+
+ $expectedParameters = [
+ 'limit',
+ 'offset',
+ 'mainlabel',
+ 'sortkeys',
+ 'querymode'
+ ];
+
+ foreach ( $expectedParameters as $key ) {
+ $this->assertArrayHasKey( $key, $serialized['parameters'] );
+ }
+ }
+
+ public function testGetHash() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getFingerprint' ] )
+ ->getMockForAbstractClass();
+
+ $instance = new Query( $description, Query::INLINE_QUERY );
+ $instance->setLimit( 50 );
+
+ $hash = $instance->getHash();
+
+ $this->assertInternalType(
+ 'string',
+ $hash
+ );
+
+ $instance->setLimit( 100 );
+
+ $this->assertNotEquals(
+ $hash,
+ $instance->getHash()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTokenTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTokenTest.php
new file mode 100644
index 00000000..b6b9e9e9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/QueryTokenTest.php
@@ -0,0 +1,219 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\DataItemFactory;
+use SMW\Query\QueryToken;
+
+/**
+ * @covers \SMW\Query\QueryToken
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QueryTokenTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ QueryToken::class,
+ new QueryToken()
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testAddFromDesciption( $description, $expected ) {
+
+ $instance = new QueryToken();
+
+ $instance->addFromDesciption( $description );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getTokens()
+ );
+ }
+
+ public function testMulitpleAddFromDesciption() {
+
+ $instance = new QueryToken();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->once() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'abc Foo 123' ) ) );
+
+ $instance->addFromDesciption( $description );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIWikiPage( '~*123 bar 456' ) ) );
+
+ $instance->addFromDesciption( $description );
+
+ $this->assertEquals(
+ [
+ 'abc' => 0,
+ 'Foo' => 1,
+ 123 => 2,
+ 'bar' => 1,
+ 456 => 2
+ ],
+ $instance->getTokens()
+ );
+ }
+
+ /**
+ * @dataProvider highlightProvider
+ */
+ public function testHighlight( $description, $text, $type, $expected ) {
+
+ $instance = new QueryToken();
+
+ $instance->addFromDesciption( $description );
+ $instance->setOutputFormat( '-hL' );
+
+ $this->assertEquals(
+ $expected,
+ $instance->highlight( $text, $type )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->once() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItemFactory->newDIBlob( 'abc Foo 123' ) ) );
+
+ $provider[] = [
+ $description,
+ [
+ 'abc' => 0,
+ 'Foo' => 1,
+ 123 => 2
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function highlightProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->any() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $description->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItemFactory->newDIBlob( 'abc Foo 123 foobar' ) ) );
+
+ $provider[] = [
+ $description,
+ 'Lorem abc foobar',
+ QueryToken::HL_BOLD,
+ "Lorem <b>abc</b> <b>foo</b>bar"
+ ];
+
+ $provider[] = [
+ $description,
+ 'Lorem abc foobar',
+ QueryToken::HL_WIKI,
+ "Lorem '''abc''' '''foo'''bar"
+ ];
+
+ $provider[] = [
+ $description,
+ 'Lorem abc foobar',
+ QueryToken::HL_UNDERLINE,
+ "Lorem <u>abc</u> <u>foo</u>bar"
+ ];
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->any() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $description->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItemFactory->newDIBlob( 'integer porttitor portt' ) ) );
+
+ $provider[] = [
+ $description,
+ 'Integer porttitor mi id ante consequat consequat <b>porttitor</b>',
+ QueryToken::HL_BOLD,
+ "<b>Integer</b> <b>porttitor</b> mi id ante consequat consequat <b><b>porttitor</b></b>"
+ ];
+
+ $provider[] = [
+ $description,
+ 'Integer porttitor mi id ante consequat consequat <b>porttitor</b>',
+ QueryToken::HL_SPAN,
+ "<span class='smw-query-token'>Integer</span> <span class='smw-query-token'>porttitor</span> mi id ante consequat consequat <b><span class='smw-query-token'>porttitor</span></b>"
+ ];
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->any() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_PRIM_LIKE ) );
+
+ $description->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItemFactory->newDIBlob( 'abc Foo 123 foobar' ) ) );
+
+ $provider[] = [
+ $description,
+ 'Lorem abc foobar',
+ QueryToken::HL_BOLD,
+ "Lorem <b>abc</b> <b>foo</b>bar"
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/RemoteRequestTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/RemoteRequestTest.php
new file mode 100644
index 00000000..46fa2be1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/RemoteRequestTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\Query\RemoteRequest;
+
+/**
+ * @covers \SMW\Query\RemoteRequest
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RemoteRequestTest extends \PHPUnit_Framework_TestCase {
+
+ private $httpRequest;
+ private $query;
+
+ protected function setUp() {
+
+ $this->httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ RemoteRequest::class,
+ new RemoteRequest( [], $this->httpRequest )
+ );
+ }
+
+ public function testGetQueryResult_CannotConnect() {
+
+ $this->httpRequest->expects( $this->once() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( false ) );
+
+ $parameters = [
+ 'url' => 'http://example.org/Foo'
+ ];
+
+ $instance = new RemoteRequest(
+ $parameters,
+ $this->httpRequest
+ );
+
+ $this->assertContains(
+ 'smw-remote-source-unavailable',
+ $instance->getQueryResult( $this->query )
+ );
+ }
+
+ public function testGetQueryResult_Connect() {
+
+ $this->httpRequest->expects( $this->once() )
+ ->method( 'ping' )
+ ->will( $this->returnValue( true ) );
+
+ $this->httpRequest->expects( $this->once() )
+ ->method( 'execute' )
+ ->will( $this->returnValue( 'Foobar' ) );
+
+ $this->httpRequest->expects( $this->once() )
+ ->method( 'getLastError' )
+ ->will( $this->returnValue( '' ) );
+
+ $parameters = [
+ 'url' => 'http://example.org/Foo'
+ ];
+
+ $instance = new RemoteRequest(
+ $parameters,
+ $this->httpRequest
+ );
+
+ $instance->clear();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Result\StringResult',
+ $instance->getQueryResult( $this->query )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/CachedQueryResultPrefetcherTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/CachedQueryResultPrefetcherTest.php
new file mode 100644
index 00000000..5c6fb56d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/CachedQueryResultPrefetcherTest.php
@@ -0,0 +1,349 @@
+<?php
+
+namespace SMW\Tests\Query\Result;
+
+use Onoi\BlobStore\BlobStore;
+use Onoi\BlobStore\Container;
+use SMW\DIWikiPage;
+use SMW\Query\Result\CachedQueryResultPrefetcher;
+use SMW\Utils\BufferedStatsdCollector;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Query\Result\CachedQueryResultPrefetcher
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class CachedQueryResultPrefetcherTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $queryFactory;
+ private $blobStore;
+ private $bufferedStatsdCollector;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->queryFactory = $this->getMockBuilder( '\SMW\QueryFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore = $this->getMockBuilder( BlobStore::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->container = $this->getMockBuilder( Container::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->bufferedStatsdCollector = $this->getMockBuilder( BufferedStatsdCollector::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CachedQueryResultPrefetcher::class,
+ new CachedQueryResultPrefetcher( $this->store, $this->queryFactory, $this->blobStore, $this->bufferedStatsdCollector )
+ );
+ }
+
+ public function testGetQueryResultForEmptyQuery() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryEngine = $this->getMockBuilder( '\SMW\QueryEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryEngine->expects( $this->once() )
+ ->method( 'getQueryResult' )
+ ->with($this->identicalTo( $query ) );
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $instance->setQueryEngine( $queryEngine );
+
+ $instance->getQueryResult( $query );
+ }
+
+ public function testGetQueryResultFromTempCache() {
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $this->container ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getQueryId' )
+ ->will( $this->returnValue( __METHOD__ ) );
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 100 ) );
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $queryEngine = $this->getMockBuilder( '\SMW\QueryEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryEngine->expects( $this->once() )
+ ->method( 'getQueryResult' )
+ ->with($this->identicalTo( $query ) );
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $instance->setQueryEngine( $queryEngine );
+
+ $instance->getQueryResult( $query );
+
+ // Second time called from tempCache
+ $instance->getQueryResult( $query );
+ }
+
+ public function testPurgeCacheByQueryList() {
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'delete' );
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $instance->resetCacheBy( [ 'Foo' ] );
+ }
+
+ public function testNoCache() {
+
+ $this->blobStore->expects( $this->never() )
+ ->method( 'read' );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 100 ) );
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->at( 2 ) )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( $query::NO_CACHE ) )
+ ->will( $this->returnValue( true ) );
+
+ $queryEngine = $this->getMockBuilder( '\SMW\QueryEngine' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $instance->setQueryEngine( $queryEngine );
+ $instance->getQueryResult( $query );
+ }
+
+ public function testMissingQueryEngineThrowsException() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getQueryResult( $query );
+ }
+
+ public function testPurgeCacheBySubject() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'delete' )
+ ->with( $this->equalTo( '1d1e1d94a78b9476c8213a16febe2c9b' ) );
+
+ $this->bufferedStatsdCollector->expects( $this->once() )
+ ->method( 'recordStats' );
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $instance->resetCacheBy( $subject );
+ }
+
+ public function testPurgeCacheBySubjectWithDependantHashIdExtension() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'delete' )
+ ->with( $this->equalTo( '1e5509cfde15f1f569db295e845ce997' ) );
+
+ $this->bufferedStatsdCollector->expects( $this->once() )
+ ->method( 'recordStats' );
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $instance->setDependantHashIdExtension( 'foo' );
+ $instance->resetCacheBy( $subject );
+ }
+
+ public function testPurgeCacheBySubjectWith_QUERY() {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject->expects( $this->atLeastOnce() )
+ ->method( 'getSubobjectName' )
+ ->will( $this->returnValue( '_QUERYfoo' ) );
+
+ $subject->expects( $this->never() )
+ ->method( 'asBase' );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'delete' )
+ ->with( $this->equalTo( 'dc63f8b4cab1bb1214979932b637cdec' ) );
+
+ $this->bufferedStatsdCollector->expects( $this->once() )
+ ->method( 'recordStats' );
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $instance->resetCacheBy( $subject );
+ }
+
+ public function testGetStats() {
+
+ $stats = [
+ 'misses' => 1,
+ 'hits' => [ 'Foo' => 2, [ 'Bar' => 2 ] ],
+ 'meta' => 'foo'
+ ];
+
+ $this->bufferedStatsdCollector->expects( $this->once() )
+ ->method( 'getStats' )
+ ->will( $this->returnValue( $stats ) );
+
+ $instance = new CachedQueryResultPrefetcher(
+ $this->store,
+ $this->queryFactory,
+ $this->blobStore,
+ $this->bufferedStatsdCollector
+ );
+
+ $stats = $instance->getStats();
+
+ $this->assertInternalType(
+ 'array',
+ $stats
+ );
+
+ $this->assertEquals(
+ [
+ 'hit' => 0.8,
+ 'miss' => 0.2
+ ],
+ $stats['ratio']
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResolverJournalTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResolverJournalTest.php
new file mode 100644
index 00000000..53b64398
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResolverJournalTest.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SMW\Tests\Query\Result;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Result\ResolverJournal;
+
+/**
+ * @covers \SMW\Query\Result\ResolverJournal
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class ResolverJournalTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ResolverJournal::class,
+ new ResolverJournal()
+ );
+ }
+
+ public function testRecordItem() {
+
+ $dataItem = DIWikiPage::newFromText( 'Foo' );
+ $instance = new ResolverJournal();
+
+ $instance->prune();
+ $instance->recordItem( $dataItem );
+
+ $this->assertEquals(
+ [ 'Foo#0##' => $dataItem ],
+ $instance->getEntityList( 'FOO:123' )
+ );
+
+ $instance->prune();
+
+ $this->assertEmpty(
+ $instance->getEntityList()
+ );
+ }
+
+ public function testRecordProperty() {
+
+ $property = new DIProperty( 'Bar' );
+ $instance = new ResolverJournal();
+
+ $instance->recordProperty( $property );
+
+ $this->assertEquals(
+ [
+ 'Bar' => $property
+ ],
+ $instance->getPropertyList()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResultFieldMatchFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResultFieldMatchFinderTest.php
new file mode 100644
index 00000000..4d44f835
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/ResultFieldMatchFinderTest.php
@@ -0,0 +1,373 @@
+<?php
+
+namespace SMW\Tests\Query\Result;
+
+use SMW\DataItemFactory;
+use SMW\DataValueFactory;
+use SMW\Query\PrintRequest;
+use SMW\Query\Result\ResultFieldMatchFinder;
+
+/**
+ * @covers SMW\Query\Result\ResultFieldMatchFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ResultFieldMatchFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $dataValueFactory;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->dataItemFactory = new DataItemFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\Query\Result\ResultFieldMatchFinder',
+ new ResultFieldMatchFinder( $store, $printRequest )
+ );
+ }
+
+ public function testGetRequestOptions() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getParameter' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\RequestOptions',
+ $instance->getRequestOptions()
+ );
+ }
+
+ public function testFindAndMatch_THIS() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->any() )
+ ->method( 'isMode' )
+ ->with($this->equalTo( PrintRequest::PRINT_THIS ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertEquals(
+ [ $dataItem ],
+ $instance->findAndMatch( $dataItem )
+ );
+ }
+
+ public function testFindAndMatch_CATS() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo' );
+ $expected = $this->dataItemFactory->newDIWikiPage( __METHOD__ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $dataItem ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_INST' ) ) )
+ ->will( $this->returnValue( [ $expected ] ) );
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->at( 1 ) )
+ ->method( 'isMode' )
+ ->with($this->equalTo( PrintRequest::PRINT_CATS ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertEquals(
+ [ $expected ],
+ $instance->findAndMatch( $dataItem )
+ );
+ }
+
+ public function testFindAndMatch_CCAT() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Bar' );
+ $expected = $this->dataItemFactory->newDIWikiPage( __METHOD__ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $dataItem ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_INST' ) ) )
+ ->will( $this->returnValue( [ $expected ] ) );
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->at( 2 ) )
+ ->method( 'isMode' )
+ ->with($this->equalTo( PrintRequest::PRINT_CCAT ) )
+ ->will( $this->returnValue( true ) );
+
+ $printRequest->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue( $expected ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertEquals(
+ [ $this->dataItemFactory->newDIBoolean( true ) ],
+ $instance->findAndMatch( $dataItem )
+ );
+ }
+
+ public function testFindAndMatch_PROP() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Bar' );
+ $expected = $this->dataItemFactory->newDIWikiPage( __METHOD__ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $dataItem ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( 'Prop' ) ) )
+ ->will( $this->returnValue( [ $expected ] ) );
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->at( 3 ) )
+ ->method( 'isMode' )
+ ->with($this->equalTo( PrintRequest::PRINT_PROP ) )
+ ->will( $this->returnValue( true ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getParameter' )
+ ->will( $this->returnValue( false ) );
+
+ $printRequest->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue( $this->dataValueFactory->newPropertyValueByLabel( 'Prop' ) ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertEquals(
+ [ $expected ],
+ $instance->findAndMatch( $dataItem )
+ );
+ }
+
+ public function testFindAndMatchWithIteratorAsValueResultOnPRINT_PROP() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Bar' );
+ $expected = $this->dataItemFactory->newDIWikiPage( __METHOD__ );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ // #2541, return an iterator
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $dataItem ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( 'Prop' ) ) )
+ ->will( $this->returnValue( new \ArrayIterator( [ $expected ] ) ) );
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->at( 3 ) )
+ ->method( 'isMode' )
+ ->with($this->equalTo( PrintRequest::PRINT_PROP ) )
+ ->will( $this->returnValue( true ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getParameter' )
+ ->will( $this->returnValue( false ) );
+
+ $printRequest->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue(
+ $this->dataValueFactory->newPropertyValueByLabel( 'Prop' ) ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertEquals(
+ [ $expected ],
+ $instance->findAndMatch( $dataItem )
+ );
+ }
+
+ public function testFindAndMatchWithBlobValueResultAndRemovedLink() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Bar' );
+ $text = $this->dataItemFactory->newDIBlob( '[[Foo::bar]]' );
+ $expected = $this->dataItemFactory->newDIBlob( 'bar' );
+
+ $propertyValue = $this->dataValueFactory->newPropertyValueByLabel( 'Prop' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ // #2541, return an iterator
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $dataItem ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( 'Prop' ) ) )
+ ->will( $this->returnValue( new \ArrayIterator( [ $text ] ) ) );
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->at( 3 ) )
+ ->method( 'isMode' )
+ ->with($this->equalTo( PrintRequest::PRINT_PROP ) )
+ ->will( $this->returnValue( true ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getParameter' )
+ ->will( $this->returnValue( false ) );
+
+ $printRequest->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue( $propertyValue ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertEquals(
+ [ $expected ],
+ $instance->findAndMatch( $dataItem )
+ );
+ }
+
+ public function testFindAndMatchWithBlobValueResultAndRetainedLink() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Bar' );
+ $text = $this->dataItemFactory->newDIBlob( '[[Foo::bar]]' );
+ $expected = $this->dataItemFactory->newDIBlob( '[[Foo::bar]]' );
+
+ $propertyValue = $this->dataValueFactory->newPropertyValueByLabel( 'Prop' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ // #2541, return an iterator
+ $store->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $dataItem ),
+ $this->equalTo( $this->dataItemFactory->newDIProperty( 'Prop' ) ) )
+ ->will( $this->returnValue( new \ArrayIterator( [ $text ] ) ) );
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->at( 3 ) )
+ ->method( 'isMode' )
+ ->with($this->equalTo( PrintRequest::PRINT_PROP ) )
+ ->will( $this->returnValue( true ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getOutputFormat' )
+ ->will( $this->returnValue( '-raw' ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getParameter' )
+ ->will( $this->returnValue( false ) );
+
+ $printRequest->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue( $propertyValue ) );
+
+ $instance = new ResultFieldMatchFinder(
+ $store,
+ $printRequest
+ );
+
+ $this->assertEquals(
+ [ $expected ],
+ $instance->findAndMatch( $dataItem )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/StringResultTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/StringResultTest.php
new file mode 100644
index 00000000..092b90b8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/Result/StringResultTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Query\Result;
+
+use SMW\Query\Result\StringResult;
+
+/**
+ * @covers \SMW\Query\Result\StringResult
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class StringResultTest extends \PHPUnit_Framework_TestCase {
+
+ private $query;
+
+ protected function setUp() {
+
+ $this->query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ StringResult::class,
+ new StringResult( '', $this->query )
+ );
+ }
+
+ public function testGetResult() {
+
+ $instance = new StringResult( 'Foobar', $this->query );
+
+ $this->assertEquals(
+ 'Foobar',
+ $instance->getResults()
+ );
+ }
+
+ public function testGetResult_PreOutputCallback() {
+
+ $instance = new StringResult( 'Foobar', $this->query );
+
+ $instance->setPreOutputCallback( function( $result, $options ) {
+ return $result . ' Foo bar';
+ } );
+
+ $this->assertEquals(
+ 'Foobar Foo bar',
+ $instance->getResults()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CategoryResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CategoryResultPrinterTest.php
new file mode 100644
index 00000000..c16262e5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CategoryResultPrinterTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace SMW\Tests\Query\ResultPrinters;
+
+use SMW\Query\ResultPrinters\CategoryResultPrinter;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\CategoryResultPrinter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CategoryResultPrinterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CategoryResultPrinter::class,
+ new CategoryResultPrinter( 'category' )
+ );
+ }
+
+ public function testGetResult_Empty() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new CategoryResultPrinter( 'category' );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getResult( $queryResult, [], SMW_OUTPUT_WIKI )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CsvFileExportPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CsvFileExportPrinterTest.php
new file mode 100644
index 00000000..564e5334
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/CsvFileExportPrinterTest.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace SMW\Tests\Query\ResultPrinters;
+
+use SMW\Query\ResultPrinters\CsvFileExportPrinter;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\CsvFileExportPrinter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CsvFileExportPrinterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CsvFileExportPrinter::class,
+ new CsvFileExportPrinter( 'csv' )
+ );
+ }
+
+ public function testGetResult_Empty() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new CsvFileExportPrinter( 'csv' );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getResult( $queryResult, [], SMW_OUTPUT_WIKI )
+ );
+ }
+
+ public function testLink() {
+
+ $link = $this->getMockBuilder( '\SMWInfolink' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getQueryLink' )
+ ->will( $this->returnValue( $link ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getCount' )
+ ->will( $this->returnValue( 1 ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new CsvFileExportPrinter( 'csv' );
+ $instance->getResult( $queryResult, [], SMW_OUTPUT_WIKI );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/FeedExportPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/FeedExportPrinterTest.php
new file mode 100644
index 00000000..d8a1fe3f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/FeedExportPrinterTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace SMW\Tests\Query\ResultPrinters;
+
+use ReflectionClass;
+use SMW\Query\ResultPrinters\FeedExportPrinter;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\FeedExportPrinter
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class FeedExportPrinterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FeedExportPrinter::class,
+ new FeedExportPrinter( 'feed' )
+ );
+ }
+
+ /**
+ * @dataProvider textDataProvider
+ */
+ public function testFeedItemDescription( $setup, $expected, $message ) {
+
+ $instance = new FeedExportPrinter( 'feed' );
+
+ $reflector = new ReflectionClass( '\SMW\Query\ResultPrinters\FeedExportPrinter' );
+ $method = $reflector->getMethod( 'feedItemDescription' );
+ $method->setAccessible( true );
+
+ $this->assertEquals(
+ $expected['text'],
+ $method->invoke( $instance, $setup['items'], $setup['pageContent'] )
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function textDataProvider() {
+
+ $provider = [];
+
+ // #0
+ // https://web.archive.org/web/20160802052417/http://www.utexas.edu/learn/html/spchar.html
+ $provider[] = [
+ [
+ 'items' => [],
+ 'pageContent' => 'Semantic MediaWiki Conference, have been announced: it will be held at' .
+ '[http://www.aohostels.com/en/tagungen/tagungen-berlin/ A&O Berlin Hauptbahnhof]' .
+ '&¢©«»—¡¿,åÃãÆç'
+ ],
+ [
+ 'text' => 'Semantic MediaWiki Conference, have been announced: it will be held at' .
+ '[http://www.aohostels.com/en/tagungen/tagungen-berlin/ A&O Berlin Hauptbahnhof]' .
+ '&¢©«»—¡¿,åÃãÆç'
+ ],
+ [ 'info' => 'text encoding including html special characters' ]
+ ];
+
+ return $provider;
+
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinter/ParameterDictionaryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinter/ParameterDictionaryTest.php
new file mode 100644
index 00000000..15a9d807
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinter/ParameterDictionaryTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace SMW\Tests\Query\ResultPrinters\ListResultPrinter;
+
+use SMW\Query\ResultPrinters\ListResultPrinter\ParameterDictionary;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\ListResultPrinter\ParameterDictionary
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author Stephan Gambke
+ */
+class ParameterDictionaryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testSetGet() {
+
+ $dict = new ParameterDictionary();
+
+ $dict->set( 'foo', 'Derek' );
+ $dict->set( 'bar', 'Devin' );
+ $dict->set( 'foo', 'Chelsea' );
+
+ $this->assertEquals( 'Chelsea', $dict->get( 'foo' ) );
+ $this->assertEquals( 'Devin', $dict->get( 'bar' ) );
+ }
+
+ public function testSetArrayGet() {
+
+ $dict = new ParameterDictionary();
+
+ $dict->set( ['foo' => 'Derek', 'bar' => 'Devin' ] );
+ $dict->set( ['foo' => 'Chelsea', 'baz' => 'Carolynn' ] );
+
+ $this->assertEquals( 'Chelsea', $dict->get( 'foo' ) );
+ $this->assertEquals( 'Devin', $dict->get( 'bar' ) );
+ $this->assertEquals( 'Carolynn', $dict->get( 'baz' ) );
+ }
+
+ public function testSetDefaultGet() {
+
+ $dict = new ParameterDictionary();
+
+ $dict->setDefault( 'foo', 'Derek' );
+ $dict->setDefault( 'bar', 'Devin' );
+ $dict->setDefault( 'foo', 'Chelsea' );
+
+ $this->assertEquals( 'Derek', $dict->get( 'foo' ) );
+ $this->assertEquals( 'Devin', $dict->get( 'bar' ) );
+ }
+
+ public function testSetDefaultArrayGet() {
+
+ $dict = new ParameterDictionary();
+
+ $dict->set( ['foo' => 'Derek', 'bar' => 'Devin' ] );
+ $dict->setDefault( ['foo' => 'Chelsea', 'baz' => 'Carolynn' ] );
+
+ $this->assertEquals( 'Derek', $dict->get( 'foo' ) );
+ $this->assertEquals( 'Devin', $dict->get( 'bar' ) );
+ $this->assertEquals( 'Carolynn', $dict->get( 'baz' ) );
+ }
+
+} \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinterTest.php
new file mode 100644
index 00000000..1c2393ee
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/ListResultPrinterTest.php
@@ -0,0 +1,66 @@
+<?php
+namespace SMW\Tests\Query\ResultPrinters;
+
+use SMW\Message;
+use SMW\Query\ResultPrinters\ListResultPrinter;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\ListResultPrinter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author Máté Szabó
+ * @author Stephan Gambke
+ */
+class ListResultPrinterTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider allFormatsProvider
+ * @param string $format
+ */
+ public function testCanConstruct( $format ) {
+ $listResultPrinter = new ListResultPrinter( $format );
+
+ $this->assertInstanceOf( '\SMW\Query\ResultPrinters\ListResultPrinter', $listResultPrinter );
+ }
+
+ /**
+ * @dataProvider allFormatsProvider
+ * @param string $format
+ */
+ public function testSupportsRecursiveAnnotation( $format ) {
+ $listResultPrinter = new ListResultPrinter( $format );
+
+ $this->assertTrue( $listResultPrinter->supportsRecursiveAnnotation() );
+ }
+
+ /**
+ * @dataProvider allFormatsProvider
+ * @param string $format
+ */
+ public function testIsDeferrable( $format ) {
+ $listResultPrinter = new ListResultPrinter( $format );
+
+ $this->assertTrue( $listResultPrinter->isDeferrable() );
+ }
+
+ /**
+ * @dataProvider allFormatsProvider
+ * @param string $format
+ */
+ public function testGetName( $format ) {
+ $listResultPrinter = new ListResultPrinter( $format );
+
+ $this->assertEquals( Message::get( 'smw_printername_' . $format ), $listResultPrinter->getName() );
+ }
+
+ public function allFormatsProvider() {
+ yield [ 'ul' ];
+ yield [ 'ol' ];
+ yield [ 'template' ];
+ yield [ 'list' ];
+ yield [ 'plainlist' ];
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/NullResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/NullResultPrinterTest.php
new file mode 100644
index 00000000..93126bd0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/NullResultPrinterTest.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace SMW\Tests\Query\ResultPrinters;
+
+use SMW\Query\ResultPrinters\NullResultPrinter;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\NullResultPrinter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class NullResultPrinterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ NullResultPrinter::class,
+ new NullResultPrinter( '' )
+ );
+ }
+
+ public function testGetResult_Empty() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new NullResultPrinter( '' );
+
+ $this->assertEmpty(
+ $instance->getResult( $queryResult, [], SMW_OUTPUT_WIKI )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TableResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TableResultPrinterTest.php
new file mode 100644
index 00000000..7ae4026c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TableResultPrinterTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace SMW\Tests\Query\ResultPrinters;
+
+use SMW\Query\ResultPrinters\TableResultPrinter;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\TableResultPrinter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TableResultPrinterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TableResultPrinter::class,
+ new TableResultPrinter( 'table' )
+ );
+ }
+
+ public function testGetResult_Empty() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new TableResultPrinter( 'table' );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getResult( $queryResult, [], SMW_OUTPUT_WIKI )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TemplateFileExportPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TemplateFileExportPrinterTest.php
new file mode 100644
index 00000000..6c700cca
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ResultPrinters/TemplateFileExportPrinterTest.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace SMW\Tests\Query\ResultPrinters;
+
+use SMW\Query\ResultPrinters\TemplateFileExportPrinter;
+
+/**
+ * @covers \SMW\Query\ResultPrinters\TemplateFileExportPrinter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TemplateFileExportPrinterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TemplateFileExportPrinter::class,
+ new TemplateFileExportPrinter( 'templatefile' )
+ );
+ }
+
+ public function testGetResult_Empty() {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new TemplateFileExportPrinter( 'templatefile' );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getResult( $queryResult, [], SMW_OUTPUT_WIKI )
+ );
+ }
+
+ public function testLink() {
+
+ $link = $this->getMockBuilder( '\SMWInfolink' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getQueryLink' )
+ ->will( $this->returnValue( $link ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getCount' )
+ ->will( $this->returnValue( 1 ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new TemplateFileExportPrinter( 'templatefile' );
+ $instance->getResult( $queryResult, [], SMW_OUTPUT_WIKI );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ScoreSetTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ScoreSetTest.php
new file mode 100644
index 00000000..32b78908
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Query/ScoreSetTest.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace SMW\Tests\Query;
+
+use SMW\DIWikiPage;
+use SMW\Query\ScoreSet;
+
+/**
+ * @covers \SMW\Query\ScoreSet
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ScoreSetTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ScoreSet::class,
+ new ScoreSet()
+ );
+ }
+
+ public function testAddScore() {
+
+ $instance = new ScoreSet();
+
+ $instance->addScore( 'Foo', 0.1 );
+
+ $this->assertEquals(
+ 0.1,
+ $instance->getScore( 'Foo' )
+ );
+
+ $this->assertFalse(
+ $instance->getScore( 'Bar' )
+ );
+ }
+
+ public function testAddScore_DIWikiPage() {
+
+ $dataItem = DIWikiPage::newFromText( 'Bar' );
+ $instance = new ScoreSet();
+
+ $instance->addScore( $dataItem, 10 );
+
+ $this->assertEquals(
+ 10,
+ $instance->getScore( $dataItem )
+ );
+ }
+
+ public function testGetScores() {
+
+ $instance = new ScoreSet();
+
+ $instance->addScore( 'Foo', 42 );
+ $instance->addScore( 'Bar', 1001 );
+
+ $this->assertEquals(
+ [
+ [ 'Foo', 42 ],
+ [ 'Bar', 1001 ]
+ ],
+ $instance->getScores()
+ );
+ }
+
+ public function testAsTable() {
+
+ $instance = new ScoreSet();
+
+ $instance->addScore( 'Foo', 42 );
+ $instance->addScore( 'Bar', 1001, 5 );
+ $instance->addScore( 'Foobar', 1 );
+
+ $table = $instance->asTable();
+
+ $this->assertContains(
+ '<tr><td>42</td><td>Foo</td><td>0</td></tr>',
+ $table
+ );
+
+ $this->assertContains(
+ '<tr><td>1001</td><td>Bar</td><td>5</td></tr>',
+ $table
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/QueryFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/QueryFactoryTest.php
new file mode 100644
index 00000000..de739997
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/QueryFactoryTest.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\QueryFactory;
+use SMW\StringCondition;
+
+/**
+ * @covers \SMW\QueryFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class QueryFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\QueryFactory',
+ new QueryFactory()
+ );
+ }
+
+ public function testCanConstructProfileAnnotatorFactory() {
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ProfileAnnotatorFactory',
+ $instance->newProfileAnnotatorFactory()
+ );
+ }
+
+ public function testCanConstructQuery() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMWQuery',
+ $instance->newQuery( $description )
+ );
+ }
+
+ public function testCanConstructDescriptionFactory() {
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\DescriptionFactory',
+ $instance->newDescriptionFactory()
+ );
+ }
+
+ public function testCanConstructPrintRequestFactory() {
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\PrintRequestFactory',
+ $instance->newPrintRequestFactory()
+ );
+ }
+
+ public function testCanConstructRequestOptions() {
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\RequestOptions',
+ $instance->newRequestOptions()
+ );
+ }
+
+ public function testCanConstructStringCondition() {
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\StringCondition',
+ $instance->newStringCondition( '', StringCondition::STRCOND_PRE )
+ );
+ }
+
+ public function testCanConstructQueryParser() {
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Query\Parser',
+ $instance->newQueryParser()
+ );
+ }
+
+ public function testCanConstructQueryResult() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $instance = new QueryFactory();
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->newQueryResult( $store, $query )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/RequestOptionsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/RequestOptionsTest.php
new file mode 100644
index 00000000..f1b01c9d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/RequestOptionsTest.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\RequestOptions;
+use SMW\StringCondition;
+
+/**
+ * @covers \SMW\RequestOptions
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class RequestOptionsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ RequestOptions::class,
+ new RequestOptions()
+ );
+ }
+
+ public function testAddStringCondition() {
+
+ $instance = new RequestOptions();
+ $instance->addStringCondition( 'Foo', StringCondition::STRCOND_PRE );
+
+ foreach ( $instance->getStringConditions() as $stringCondition ) {
+ $this->assertInstanceOf(
+ '\SMW\StringCondition',
+ $stringCondition
+ );
+
+ $this->assertFalse(
+ $stringCondition->isOr
+ );
+ }
+
+ $this->assertEquals(
+ '[-1,0,false,true,null,true,"Foo#0##",[],[]]',
+ $instance->getHash()
+ );
+ }
+
+ public function testEddExtraCondition() {
+
+ $instance = new RequestOptions();
+ $instance->addExtraCondition( 'Foo' );
+ $instance->addExtraCondition( [ 'Bar' => 'Foobar' ] );
+
+ $this->assertEquals(
+ [
+ 'Foo',
+ [ 'Bar' => 'Foobar' ]
+ ],
+ $instance->getExtraConditions()
+ );
+
+ $this->assertEquals(
+ '[-1,0,false,true,null,true,"",["Foo",{"Bar":"Foobar"}],[]]',
+ $instance->getHash()
+ );
+ }
+
+ /**
+ * @dataProvider numberProvider
+ */
+ public function testLimit( $limit, $expected ) {
+
+ $instance = new RequestOptions();
+ $instance->setLimit( $limit );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getLimit()
+ );
+
+ $instance->limit = $limit;
+
+ $this->assertEquals(
+ $expected,
+ $instance->getLimit()
+ );
+ }
+
+ /**
+ * @dataProvider numberProvider
+ */
+ public function testOffset( $offset, $expected ) {
+
+ $instance = new RequestOptions();
+ $instance->setOffset( $offset );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getOffset()
+ );
+
+ $instance->offset = $offset;
+
+ $this->assertEquals(
+ $expected,
+ $instance->getOffset()
+ );
+ }
+
+ public function numberProvider() {
+
+ $provider[] = [
+ 42,
+ 42
+ ];
+
+ $provider[] = [
+ '42foo',
+ 42
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Rule/RuleTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Rule/RuleTest.php
new file mode 100644
index 00000000..eacef617
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Rule/RuleTest.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace SMW\Tests\Rule;
+
+use SMW\Rule\Rule;
+
+/**
+ * @covers \SMW\Rule\Rule
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class RuleTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new Rule( 'foo', [], [] );
+
+ $this->assertInstanceof(
+ Rule::class,
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/BadHttpEndpointResponseExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/BadHttpEndpointResponseExceptionTest.php
new file mode 100644
index 00000000..54355886
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/BadHttpEndpointResponseExceptionTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\Exception;
+
+use SMW\SPARQLStore\Exception\BadHttpEndpointResponseException;
+
+/**
+ * @covers \SMW\SPARQLStore\Exception\BadHttpEndpointResponseException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class BadHttpEndpointResponseExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\Exception\BadHttpEndpointResponseException',
+ new BadHttpEndpointResponseException( 'Foo', 'Bar', 'Que' )
+ );
+ }
+
+ /**
+ * @dataProvider errorCodeProvider
+ */
+ public function testErrorCodes( $errorCode ) {
+
+ $instance = new BadHttpEndpointResponseException( $errorCode, '', '' );
+ $this->assertEquals( $errorCode, $instance->getCode() );
+ }
+
+ public function errorCodeProvider() {
+
+ $provider = [
+ [ BadHttpEndpointResponseException::ERROR_MALFORMED ],
+ [ BadHttpEndpointResponseException::ERROR_REFUSED ],
+ [ BadHttpEndpointResponseException::ERROR_GRAPH_NOEXISTS ],
+ [ BadHttpEndpointResponseException::ERROR_GRAPH_EXISTS ],
+ [ BadHttpEndpointResponseException::ERROR_OTHER ],
+ [ BadHttpEndpointResponseException::ERROR_NOSERVICE ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/HttpEndpointConnectionExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/HttpEndpointConnectionExceptionTest.php
new file mode 100644
index 00000000..c0843f9e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/Exception/HttpEndpointConnectionExceptionTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\Exception;
+
+use SMW\SPARQLStore\Exception\HttpEndpointConnectionException;
+
+/**
+ * @covers \SMW\SPARQLStore\Exception\HttpEndpointConnectionException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class HttpEndpointConnectionExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ HttpEndpointConnectionException::class,
+ new HttpEndpointConnectionException( 'Foo', 'Bar', 'Que' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/HttpResponseErrorMapperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/HttpResponseErrorMapperTest.php
new file mode 100644
index 00000000..7467e523
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/HttpResponseErrorMapperTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\SPARQLStore\HttpResponseErrorMapper;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\HttpResponseErrorMapper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class HttpResponseErrorMapperTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ HttpResponseErrorMapper::class,
+ new HttpResponseErrorMapper( $httpRequest )
+ );
+ }
+
+ /**
+ * @dataProvider curlErrorCodeThatNotThrowsExceptionProvider
+ */
+ public function testResponseToHttpRequestThatNotThrowsException( $curlErrorCode ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastErrorCode' )
+ ->will( $this->returnValue( $curlErrorCode ) );
+
+ $instance = new HttpResponseErrorMapper( $httpRequest );
+ $instance->mapErrorResponse( 'Foo', 'Bar' );
+ }
+
+ public function testResponseToHttpRequestForInvalidErrorCodeThrowsException() {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastErrorCode' )
+ ->will( $this->returnValue( 99999 ) );
+
+ $instance = new HttpResponseErrorMapper( $httpRequest );
+
+ $this->setExpectedException( '\SMW\SPARQLStore\Exception\HttpEndpointConnectionException' );
+ $instance->mapErrorResponse( 'Foo', 'Bar' );
+ }
+
+ /**
+ * @dataProvider httpCodeThatThrowsExceptionProvider
+ */
+ public function testResponseToHttpRequesForHttpErrorThatThrowsException( $httpErrorCode ) {
+
+ // PHP doesn't know CURLE_HTTP_RETURNED_ERROR therefore using 22
+ // http://curl.haxx.se/libcurl/c/libcurl-errors.html
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastErrorCode' )
+ ->will( $this->returnValue( 22 ) );
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastTransferInfo' )
+ ->with( $this->equalTo( CURLINFO_HTTP_CODE ) )
+ ->will( $this->returnValue( $httpErrorCode ) );
+
+ $instance = new HttpResponseErrorMapper( $httpRequest );
+
+ $this->setExpectedException( '\SMW\SPARQLStore\Exception\BadHttpEndpointResponseException' );
+ $instance->mapErrorResponse( 'Foo', 'Bar' );
+ }
+
+ public function testResponseToHttpRequesForHttpErrorThatNotThrowsException() {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastErrorCode' )
+ ->will( $this->returnValue( 22 ) );
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastTransferInfo' )
+ ->with( $this->equalTo( CURLINFO_HTTP_CODE ) )
+ ->will( $this->returnValue( 404 ) );
+
+ $instance = new HttpResponseErrorMapper( $httpRequest );
+ $instance->mapErrorResponse( 'Foo', 'Bar' );
+ }
+
+ public function curlErrorCodeThatNotThrowsExceptionProvider() {
+
+ $provider = [
+ [ CURLE_GOT_NOTHING ],
+ [ CURLE_COULDNT_CONNECT ]
+ ];
+
+ return $provider;
+ }
+
+ public function httpCodeThatThrowsExceptionProvider() {
+
+ $provider = [
+ [ 400 ],
+ [ 500 ]
+ ];
+
+ return $provider;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FalseConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FalseConditionTest.php
new file mode 100644
index 00000000..95782d04
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FalseConditionTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\Condition;
+
+use SMW\SPARQLStore\QueryEngine\Condition\FalseCondition;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\Condition\FalseCondition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class FalseConditionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\SPARQLStore\QueryEngine\Condition\FalseCondition',
+ new FalseCondition()
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $instance = new FalseCondition();
+
+ $this->assertNotEmpty(
+ $instance->getCondition()
+ );
+
+ $this->assertTrue(
+ $instance->isSafe()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FilterConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FilterConditionTest.php
new file mode 100644
index 00000000..18a8422e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/FilterConditionTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\Condition;
+
+use SMW\SPARQLStore\QueryEngine\Condition\FilterCondition;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\Condition\FilterCondition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class FilterConditionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\SPARQLStore\QueryEngine\Condition\FilterCondition',
+ new FilterCondition( 'condition' )
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $instance = new FilterCondition( 'filter' );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getCondition()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->namespaces
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getWeakConditionString()
+ );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->isSafe()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/SingletonConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/SingletonConditionTest.php
new file mode 100644
index 00000000..016bc384
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/SingletonConditionTest.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\Condition;
+
+use SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SingletonConditionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $expElement = $this->getMockBuilder( '\SMWExpElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition',
+ new SingletonCondition( $expElement )
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $expElement = $this->getMockBuilder( '\SMWExpElement' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SingletonCondition( $expElement );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getCondition()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getWeakConditionString()
+ );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->isSafe()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/TrueConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/TrueConditionTest.php
new file mode 100644
index 00000000..a404712e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/TrueConditionTest.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\Condition;
+
+use SMW\SPARQLStore\QueryEngine\Condition\TrueCondition;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\Condition\TrueCondition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class TrueConditionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\SPARQLStore\QueryEngine\Condition\TrueCondition',
+ new TrueCondition()
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $instance = new TrueCondition();
+
+ $this->assertEmpty(
+ $instance->getCondition()
+ );
+
+ $this->assertFalse(
+ $instance->isSafe()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/WhereConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/WhereConditionTest.php
new file mode 100644
index 00000000..c1d5cdac
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/Condition/WhereConditionTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\Condition;
+
+use SMW\SPARQLStore\QueryEngine\Condition\WhereCondition;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\Condition\WhereCondition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class WhereConditionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ 'SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ new WhereCondition( 'condition', true )
+ );
+ }
+
+ public function testCommonMethods() {
+
+ $instance = new WhereCondition( 'condition', true );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getCondition()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->namespaces
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getWeakConditionString()
+ );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->isSafe()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/ConditionBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/ConditionBuilderTest.php
new file mode 100644
index 00000000..982ef551
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/ConditionBuilderTest.php
@@ -0,0 +1,923 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDataItem as DataItem;
+use SMWDIBlob as DIBlob;
+use SMWDINumber as DINumber;
+use SMWDITime as DITime;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\ConditionBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ConditionBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $stringBuilder;
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ConditionBuilder::class,
+ new ConditionBuilder( $this->descriptionInterpreterFactory )
+ );
+ }
+
+ public function testQueryForSingleProperty() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQuerySomeProperty_ForKnownSortPropertyKey() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance
+ ->setSortKeys( [ 'Foo' => 'DESC' ] )
+ ->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( '{ ?v1 swivt:wikiPageSortKey ?v1sk .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQuerySomeProperty_ForUnknownSortPropertyKey() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance
+ ->setSortKeys( [ 'Bar' => 'DESC' ] )
+ ->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Bar ?v2 .' )->addNewLine()
+ ->addString( '{ ?v2 swivt:wikiPageSortKey ?v2sk .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQuerySomeProperty_ForEmptySortPropertyKey() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance
+ ->setSortKeys( [ '' => 'DESC' ] )
+ ->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQuerySomeProperty_OnInvalidSortKeyThrowsException() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $instance->setSortKeys( [ 'Foo', 'ASC' ] );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getConditionFrom( $description );
+ }
+
+ public function testQueryForSinglePropertyWithValue() {
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' )
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '"SomePropertyValue" swivt:page ?url .' )->addNewLine()
+ ->addString( ' OPTIONAL { "SomePropertyValue" swivt:redirectsTo ?o1 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o1 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForSomePropertyWithValue() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIBlob( 'SomePropertyBlobValue' ) )
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Foo "SomePropertyBlobValue" .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForSinglePageTypePropertyWithValueComparator() {
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIWikiPage( 'SomePropertyPageValue', NS_MAIN ), null, SMW_CMP_LEQ )
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1sk <= "SomePropertyPageValue" )' )->addNewLine()
+ ->addString( '?v1 swivt:wikiPageSortKey ?v1sk .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForSingleBlobTypePropertyWithNotLikeComparator() {
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIBlob( 'SomePropertyBlobValue' ), null, SMW_CMP_NLKE )
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( !regex( ?v1, "^SomePropertyBlobValue$", "s") )' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForSingleCategory() {
+
+ $category = new DIWikiPage( 'Foo', NS_CATEGORY, '' );
+
+ $categoryName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $category )
+ );
+
+ $description = new ClassDescription(
+ $category
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( "{ ?result rdf:type $categoryName . }" )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o1 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o1 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForSingleNamespace() {
+
+ $description = new NamespaceDescription( NS_HELP );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $this->assertSame( 12, NS_HELP );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '{ ?result swivt:wikiNamespace "12"^^xsd:integer . }' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o1 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o1 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForPropertyConjunction() {
+
+ $conjunction = new Conjunction( [
+ new SomeProperty(
+ new DIProperty( 'Foo' ), new ValueDescription( new DIBlob( 'SomePropertyValue' ) ) ),
+ new SomeProperty(
+ new DIProperty( 'Bar' ), new ThingDescription() ),
+ ] );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $conjunction );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Foo "SomePropertyValue" .' )->addNewLine()
+ ->addString( '?result property:Bar ?v2 .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForPropertyConjunctionWithGreaterLessEqualFilter() {
+
+ $conjunction = new Conjunction( [
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ValueDescription( new DINumber( 1 ), null, SMW_CMP_GEQ ) ),
+ new SomeProperty(
+ new DIProperty( 'Bar' ),
+ new ValueDescription( new DINumber( 9 ), null, SMW_CMP_LEQ ) ),
+ ] );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $conjunction );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1 >= "1"^^xsd:double )' )->addNewLine()
+ ->addString( '?result property:Bar ?v2 .' )->addNewLine()
+ ->addString( 'FILTER( ?v2 <= "9"^^xsd:double )' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForPropertyDisjunction() {
+
+ $conjunction = new Disjunction( [
+ new SomeProperty( new DIProperty( 'Foo' ), new ThingDescription() ),
+ new SomeProperty( new DIProperty( 'Bar' ), new ThingDescription() )
+ ] );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $conjunction );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '{' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( '} UNION {' )->addNewLine()
+ ->addString( '?result property:Bar ?v2 .' )->addNewLine()
+ ->addString( '}' )
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testQueryForPropertyDisjunctionWithLikeNotLikeFilter() {
+
+ $conjunction = new Disjunction( [
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ValueDescription( new DIBlob( "AA*" ), null, SMW_CMP_LIKE ) ),
+ new SomeProperty(
+ new DIProperty( 'Bar' ),
+ new ValueDescription( new DIBlob( "BB?" ), null, SMW_CMP_NLKE ) )
+ ] );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $conjunction );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '{' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( regex( ?v1, "^AA.*$", "s") )' )->addNewLine()
+ ->addString( '} UNION {' )->addNewLine()
+ ->addString( '?result property:Bar ?v2 .' )->addNewLine()
+ ->addString( 'FILTER( !regex( ?v2, "^BB.$", "s") )' )->addNewLine()
+ ->addString( '}' )
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testSingleDatePropertyWithGreaterEqualConstraint() {
+
+ $property = new DIProperty( 'SomeDateProperty' );
+ $property->setPropertyTypeId( '_dat' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DITime( 1, 1970, 01, 01, 1, 1 ), null, SMW_CMP_GEQ )
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:SomeDateProperty-23aux ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1 >= "2440587.5423611"^^xsd:double )' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testSingleSubobjectBuildAsAuxiliaryProperty() {
+
+ $property = new DIProperty( '_SOBJ' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Has_subobject ?v1 .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ /**
+ * '[[HasSomeProperty::Foo||Bar]]'
+ */
+ public function testSubqueryDisjunction() {
+
+ $property = new DIProperty( 'HasSomeProperty' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $disjunction = new Disjunction( [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ), $property ),
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ), $property )
+ ] );
+
+ $description = new SomeProperty(
+ $property,
+ $disjunction
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:HasSomeProperty ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1 = wiki:Foo || ?v1 = wiki:Bar )' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ /**
+ * '[[Born in::<q>[[Category:City]] [[Located in::Outback]]</q>]]'
+ */
+ public function testNestedPropertyConjunction() {
+
+ $property = DIProperty::newFromUserLabel( 'Born in' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $category = new DIWikiPage( 'City', NS_CATEGORY );
+
+ $categoryName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $category )
+ );
+
+ $conjunction = new Conjunction( [
+ new ClassDescription( $category ),
+ new SomeProperty(
+ DIProperty::newFromUserLabel( 'Located in' ),
+ new ValueDescription(
+ new DIWikiPage( 'Outback', NS_MAIN ),
+ DIProperty::newFromUserLabel( 'Located in' ) )
+ )
+ ]
+ );
+
+ $description = new SomeProperty(
+ $property,
+ $conjunction
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:Born_in ?v1 .' )->addNewLine()
+ ->addString( '{ ' )
+ ->addString( "{ ?v1 rdf:type $categoryName . }" )->addNewLine()
+ ->addString( '?v1 property:Located_in wiki:Outback .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ /**
+ * '[[LocatedIn.MemberOf::Wonderland]]'
+ */
+ public function testPropertyChain() {
+
+ $description = new SomeProperty(
+ DIProperty::newFromUserLabel( 'LocatedIn' ),
+ new SomeProperty(
+ DIProperty::newFromUserLabel( 'MemberOf' ),
+ new ValueDescription(
+ new DIWikiPage( 'Wonderland', NS_MAIN, '' ),
+ DIProperty::newFromUserLabel( 'MemberOf' ), SMW_CMP_EQ
+ )
+ )
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result property:LocatedIn ?v1 .' )->addNewLine()
+ ->addString( '{ ?v1 property:MemberOf wiki:Wonderland .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testAddOrderByData_ForNonWikiPageType() {
+
+ $condition = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $instance->addOrderByData( $condition, 'foo', DataItem::TYPE_NUMBER );
+
+ $this->assertEquals(
+ 'foo',
+ $condition->orderByVariable
+ );
+ }
+
+ public function testAddOrderByData_ForWikiPageType() {
+
+ $condition = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $instance->addOrderByData( $condition, 'foo', DataItem::TYPE_WIKIPAGE );
+
+ $this->assertEquals(
+ 'foosk',
+ $condition->orderByVariable
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?foo swivt:wikiPageSortKey ?foosk .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $condition->weakConditions['foosk']
+ );
+ }
+
+ public function testCanUseQFeature() {
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->isSetFlag( 'Foo' )
+ );
+ }
+
+ public function testTryToFindRedirectVariableForNonWpgDataItem() {
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $this->assertNull(
+ $instance->tryToFindRedirectVariableForDataItem( new DINumber( 1 ) )
+ );
+ }
+
+ public function testExtendConditionUsingPropertyPathForWpgPropertyValueRedirect() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( true ) );
+
+ $diWikiPage = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->setConstructorArgs( [ 'Bar', NS_MAIN ] )
+ ->setMethods( [ 'getTitle' ] )
+ ->getMock();
+
+ $diWikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( $diWikiPage, $property )
+ );
+
+ $instance = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->setConstructorArgs( [ $this->descriptionInterpreterFactory ] )
+ ->setMethods( [ 'isSetFlag' ] )
+ ->getMock();
+
+ $instance->expects( $this->at( 0 ) )
+ ->method( 'isSetFlag' )
+ ->with( $this->equalTo( SMW_SPARQL_QF_NOCASE ) )
+ ->will( $this->returnValue( false ) );
+
+ $instance->expects( $this->at( 1 ) )
+ ->method( 'isSetFlag' )
+ ->with( $this->equalTo( SMW_SPARQL_QF_REDI ) )
+ ->will( $this->returnValue( true ) );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?r2 ^swivt:redirectsTo wiki:Bar .' )->addNewLine()
+ ->addString( '?result property:Foo ?r2 .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o3 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o3 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testExtendConditionUsingPropertyPathForWpgValueRedirect() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->atLeastOnce() )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( true ) );
+
+ $diWikiPage = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->setConstructorArgs( [ 'Bar', NS_MAIN ] )
+ ->setMethods( [ 'getTitle' ] )
+ ->getMock();
+
+ $diWikiPage->expects( $this->atLeastOnce() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $description = new ValueDescription( $diWikiPage, null );
+
+ $instance = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->setConstructorArgs( [ $this->descriptionInterpreterFactory ] )
+ ->setMethods( [ 'isSetFlag' ] )
+ ->getMock();
+
+ $instance->expects( $this->at( 0 ) )
+ ->method( 'isSetFlag' )
+ ->with( $this->equalTo( SMW_SPARQL_QF_NOCASE ) )
+ ->will( $this->returnValue( false ) );
+
+ $instance->expects( $this->at( 1 ) )
+ ->method( 'isSetFlag' )
+ ->with( $this->equalTo( SMW_SPARQL_QF_REDI ) )
+ ->will( $this->returnValue( true ) );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?r1 ^swivt:redirectsTo wiki:Bar .' )->addNewLine()
+ ->addString( 'FILTER( ?result = ?r1 )' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+ public function testSingletonLikeConditionForSolitaryWpgValue() {
+
+ $description = new ValueDescription(
+ new DIWikiPage( "Foo*", NS_MAIN ), null, SMW_CMP_LIKE
+ );
+
+ $instance = new ConditionBuilder( $this->descriptionInterpreterFactory );
+
+ $condition = $instance->getConditionFrom( $description );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition',
+ $condition
+ );
+
+ $expectedConditionString = $this->stringBuilder
+ ->addString( 'FILTER( regex( ?v1, "^Foo.*$", "s") )' )->addNewLine()
+ ->addString( '?result swivt:wikiPageSortKey ?v1 .' )->addNewLine()
+ ->addString( ' OPTIONAL { ?result swivt:redirectsTo ?o2 } .' )->addNewLine()
+ ->addString( ' FILTER ( !bound( ?o2 ) ) .' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $instance->convertConditionToString( $condition )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php
new file mode 100644
index 00000000..8e4be5e7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine;
+
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DescriptionInterpreterFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory',
+ new DescriptionInterpreterFactory()
+ );
+ }
+
+ public function testCanConstructDispatchingDescriptionInterpreter() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DescriptionInterpreterFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\DispatchingDescriptionInterpreter',
+ $instance->newDispatchingDescriptionInterpreter( $conditionBuilder )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php
new file mode 100644
index 00000000..026ace2d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php
@@ -0,0 +1,240 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter;
+use SMW\SPARQLStore\QueryEngine\EngineOptions;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ClassDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter',
+ new ClassDescriptionInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanBuildConditionFor() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ClassDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ClassDescriptionInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider categoryProvider
+ */
+ public function testClassConditionForCategories( $description, $orderByProperty, $expectedConditionType, $expectedConditionString ) {
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new ClassDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function testHierarchyPattern() {
+
+ $engineOptions = new EngineOptions();
+ $engineOptions->set( 'smwgSparqlQFeatures', SMW_SPARQL_QF_SUBC );
+
+ $category = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $categoryName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $category )
+ );
+
+ $hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $hierarchyLookup->expects( $this->once() )
+ ->method( 'hasSubcategory' )
+ ->with( $this->equalTo( $category ) )
+ ->will( $this->returnValue( true ) );
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory, $engineOptions );
+ $conditionBuilder->setHierarchyLookup( $hierarchyLookup );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+
+ $instance = new ClassDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription(
+ new ClassDescription( $category )
+ );
+
+ $expected = UtilityFactory::getInstance()->newStringBuilder()
+ ->addString( '{' )->addNewLine()
+ ->addString( "?sc1 rdfs:subClassOf* $categoryName ." )->addNewLine()
+ ->addString( '?result rdf:type ?sc1 . }' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expected,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function categoryProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition';
+
+ $description = new ClassDescription( [] );
+ $orderByProperty = null;
+
+ $expected = $stringBuilder
+ ->addString( '<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected
+ ];
+
+ # 1
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $category = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $categoryName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $category )
+ );
+
+ $description = new ClassDescription( $category );
+ $orderByProperty = null;
+
+ $expected = $stringBuilder
+ ->addString( "{ ?result rdf:type $categoryName . }" )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected,
+ ];
+
+ # 2
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $categoryFoo = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $categoryFooName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $categoryFoo )
+ );
+
+ $categoryBar = new DIWikiPage( 'Bar', NS_CATEGORY );
+
+ $categoryBarName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $categoryBar )
+ );
+
+ $description = new ClassDescription( [
+ $categoryFoo,
+ $categoryBar
+ ] );
+
+ $orderByProperty = null;
+
+ $expected = $stringBuilder
+ ->addString( "{ ?result rdf:type $categoryFooName . }" )->addNewLine()
+ ->addString( 'UNION' )->addNewLine()
+ ->addString( "{ ?result rdf:type $categoryBarName . }" )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected
+ ];
+
+ # 3
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new ClassDescription( [
+ $categoryFoo,
+ $categoryBar
+ ] );
+
+ $orderByProperty = new DIProperty( 'Foo' );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( "{ ?result rdf:type $categoryFooName . }" )->addNewLine()
+ ->addString( 'UNION' )->addNewLine()
+ ->addString( "{ ?result rdf:type $categoryBarName . }" )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php
new file mode 100644
index 00000000..308e7196
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php
@@ -0,0 +1,198 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\ApplicationFactory;
+use SMW\DIConcept;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ConceptDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ConceptDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter',
+ new ConceptDescriptionInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanBuildConditionFor() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ConceptDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ConceptDescriptionInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testConceptDescriptionInterpreter( $description, $orderByProperty, $expectedConditionType, $expectedConditionString ) {
+
+ $resultVariable = 'result';
+
+ $circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setCircularReferenceGuard( $circularReferenceGuard );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new ConceptDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function testConceptDescriptionInterpreterForAnyValueConceptUsingMockedStore() {
+
+ $circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with( $this->equalTo( new DIProperty( '_CONC' ) ) )
+ ->will( $this->returnValue( [
+ new DIConcept( '[[Foo::+]]', 'Bar', 1, 0, 0 ) ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getSemanticData' )
+ ->with( $this->equalTo( new DIWikiPage( 'Foo', SMW_NS_CONCEPT ) ) )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $description = new ConceptDescription( new DIWikiPage( 'Foo', SMW_NS_CONCEPT ) );
+ $orderByProperty = null;
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setCircularReferenceGuard( $circularReferenceGuard );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new ConceptDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $expectedConditionString = UtilityFactory::getInstance()->newStringBuilder()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->getString();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition',
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition';
+
+ $description = new ConceptDescription( new DIWikiPage( 'Foo', SMW_NS_CONCEPT ) );
+ $orderByProperty = null;
+
+ $expected = $stringBuilder
+ ->addString( '<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php
new file mode 100644
index 00000000..d3e2ff1a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ConjunctionInterpreterTest.php
@@ -0,0 +1,369 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ConjunctionInterpreter;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ConjunctionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ConjunctionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ConjunctionInterpreter',
+ new ConjunctionInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanBuildConditionFor() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Conjunction' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ConjunctionInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testConjunctionCondition( $description, $orderByProperty, $sortkeys, $expectedConditionType, $expectedConditionString ) {
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setSortKeys( $sortkeys );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new ConjunctionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\TrueCondition';
+
+ $description = new Conjunction();
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 1
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition';
+
+ $description = new Conjunction( [
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) )
+ ] );
+
+ $description = new Conjunction( [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ $description
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 2
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\TrueCondition';
+
+ $description = new Conjunction( [ new ThingDescription() ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 3
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ new ThingDescription()
+ );
+
+ $description = new Conjunction( [
+ $description,
+ new NamespaceDescription( NS_HELP )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( '{ ?result swivt:wikiNamespace "12"^^xsd:integer . }' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 4
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition';
+
+ $description = new Conjunction( [
+ new NamespaceDescription( NS_MAIN ),
+ new ValueDescription( new DIWikiPage( 'SomePageValue', NS_MAIN ) )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '{ wiki:SomePageValue swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 5
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyBlobValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LESS
+ );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ $description
+ );
+
+ $description = new Conjunction( [
+ $description,
+ new ValueDescription( new DIBlob( 'SomeOtherPropertyBlobValue' ), null, SMW_CMP_LESS ),
+ new ValueDescription( new DIBlob( 'YetAnotherPropertyBlobValue' ), null, SMW_CMP_GRTR ),
+ new NamespaceDescription( NS_MAIN )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1 < "SomePropertyBlobValue" )' )->addNewLine()
+ ->addString( '{ ?result swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->addString( 'FILTER( ?result < "SomeOtherPropertyBlobValue" && ?result > "YetAnotherPropertyBlobValue" )' )
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 6
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyBlobValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LESS
+ );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ $description
+ );
+
+ $description = new Conjunction( [
+ $description,
+ new ValueDescription( new DIBlob( 'SomeOtherPropertyBlobValue' ), null, SMW_CMP_LIKE ),
+ new ValueDescription( new DIWikiPage( 'SomePropertyPageValue', NS_MAIN ) ),
+ new NamespaceDescription( NS_MAIN )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( 'wiki:SomePropertyPageValue property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1 < "SomePropertyBlobValue" )' )->addNewLine()
+ ->addString( '{ wiki:SomePropertyPageValue swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->addString( 'FILTER( regex( ?result, "^SomeOtherPropertyBlobValue$", "s") )' )
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 7
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new Conjunction( [
+ new ValueDescription( new DIBlob( 'SomeOtherPropertyBlobValue' ), null, SMW_CMP_LIKE ),
+ new ValueDescription( new DIBlob( 'YetAnotherPropertyBlobValue' ), new DIProperty( 'Foo'), SMW_CMP_NLKE ),
+ new ThingDescription()
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( regex( ?result, "^SomeOtherPropertyBlobValue$", "s") && ' )
+ ->addString( '!regex( ?result, "^YetAnotherPropertyBlobValue$", "s") )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 8
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $propertyValue = new DIWikiPage( 'SomePropertyPageValue', NS_HELP );
+
+ $propertyValueName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $propertyValue )
+ );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ValueDescription( $propertyValue )
+ );
+
+ $category = new DIWikiPage( 'Bar', NS_CATEGORY );
+
+ $categoryName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $category )
+ );
+
+ $description = new Conjunction([
+ $description,
+ new ClassDescription( $category )
+ ] );
+
+ $orderByProperty = new DIProperty( 'Foo' );
+ $sortkeys = [ 'Foo' => 'ASC' ];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( "?result property:Foo $propertyValueName ." )->addNewLine()
+ ->addString( '{ ?v1 swivt:wikiPageSortKey ?v1sk .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->addString( "{ ?result rdf:type $categoryName . }" )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/DisjunctionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/DisjunctionInterpreterTest.php
new file mode 100644
index 00000000..41ce70cb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/DisjunctionInterpreterTest.php
@@ -0,0 +1,483 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\DisjunctionInterpreter;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+use SMWDINumber as DINumber;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\DisjunctionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class DisjunctionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\DisjunctionInterpreter',
+ new DisjunctionInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanBuildConditionFor() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Disjunction' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DisjunctionInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testConjunctionCondition( $description, $orderByProperty, $sortkeys, $expectedConditionType, $expectedConditionString ) {
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setSortKeys( $sortkeys );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new DisjunctionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition';
+
+ $description = new Disjunction();
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 1
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition';
+
+ $description = new Disjunction( [
+ new ThingDescription(),
+ new ThingDescription()
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 2
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new Disjunction( [
+ new NamespaceDescription( NS_MAIN ),
+ new NamespaceDescription( NS_HELP )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '{' )->addNewLine()
+ ->addString( '{ ?result swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->addString( '} UNION {' )->addNewLine()
+ ->addString( '{ ?result swivt:wikiNamespace "12"^^xsd:integer . }' )->addNewLine()
+ ->addString( '}' )
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 3
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new Disjunction( [
+ new NamespaceDescription( NS_MAIN )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '{ ?result swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 4
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition';
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'SomePropertyPageValue', NS_MAIN ), null, SMW_CMP_LIKE
+ );
+
+ $description = new Disjunction( [
+ $description
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( 'FILTER( regex( ?v1, "^SomePropertyPageValue$", "s") )' )->addNewLine()
+ ->addString( '?result swivt:wikiPageSortKey ?v1 .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 5
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new Disjunction( [
+ new NamespaceDescription( NS_MAIN ),
+ new ValueDescription( new DIBlob( 'SomePropertyBlobValue' ), new DIProperty( 'Foo' ), SMW_CMP_LESS )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'OPTIONAL { {' )->addNewLine()
+ ->addString( '{ ?v1 swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->addString( '} }' )->addNewLine()
+ ->addString( ' FILTER( ?result < "SomePropertyBlobValue" || ?result = ?v1 )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 6
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyBlobValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LESS
+ );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ $description
+ );
+
+ $description = new Disjunction( [
+ new NamespaceDescription( NS_MAIN ),
+ $description
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '{' )->addNewLine()
+ ->addString( '{ ?result swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->addString( '} UNION {' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1 < "SomePropertyBlobValue" )' )->addNewLine()
+ ->addString( '}' )
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 7
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyBlobValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_EQ
+ );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ $description
+ );
+
+ $description = new Disjunction( [
+ new NamespaceDescription( NS_MAIN ),
+ $description,
+ new ValueDescription( new DINumber( 42 ), null, SMW_CMP_EQ )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'OPTIONAL { {' )->addNewLine()
+ ->addString( '{ ?v2 swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->addString( '} UNION {' )->addNewLine()
+ ->addString( '?v2 property:Foo "SomePropertyBlobValue" .' )->addNewLine()
+ ->addString( '} }' )->addNewLine()
+ ->addString( ' FILTER( ?result = "42"^^xsd:double || ?result = ?v2 )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 8
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\TrueCondition';
+
+ $description = new Disjunction( [
+ new ValueDescription( new DINumber( 12 ), null, SMW_CMP_EQ )
+ ] );
+
+ $description = new Disjunction( [
+ $description,
+ new ValueDescription( new DINumber( 42 ), null, SMW_CMP_LIKE )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 9
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new Disjunction( [
+ new ValueDescription( new DINumber( 12 ), null, SMW_CMP_EQ ),
+ new ValueDescription( new DIBlob( 'Bar' ), null, SMW_CMP_LIKE )
+ ] );
+
+ $description = new Disjunction( [
+ $description,
+ new SomeProperty(
+ new DIProperty( 'Foo' ),
+ new ValueDescription( new DINumber( 42 ), null, SMW_CMP_LIKE )
+ )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'OPTIONAL { {' )->addNewLine()
+ ->addString( '?v2 property:Foo ?v1 .' )->addNewLine()
+ ->addString( '} }' )->addNewLine()
+ ->addString( ' FILTER( ?result = "12"^^xsd:double || regex( ?result, "^Bar$", "s") || ?result = ?v2 )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 10
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new Disjunction( [
+ new Conjunction( [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_EQ ),
+ new SomeProperty(
+ new DIProperty( 'Bar' ),
+ new ThingDescription()
+ )
+ ] ),
+ new ValueDescription( new DIBlob( 'Yui' ), null, SMW_CMP_LIKE )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [ 'Bar' => 'ASC' ];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'OPTIONAL { {' )->addNewLine()
+ ->addString( '?v2 property:Bar ?v1 .' )->addNewLine()
+ ->addString( '{ ?v1 swivt:wikiPageSortKey ?v1sk .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->addString( ' FILTER( ?v2 = wiki:Foo ) } }' )->addNewLine()
+ ->addString( ' FILTER( regex( ?result, "^Yui$", "s") || ?result = ?v2 )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 11
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new Disjunction( [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_EQ ),
+ new ValueDescription( new DIBlob( 'Yui' ), null, SMW_CMP_LIKE )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( ?result = wiki:Foo || regex( ?result, "^Yui$", "s") )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 12
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition';
+
+ $description = new Conjunction( [
+ new ValueDescription( new DIWikiPage( 'Bar', NS_MAIN ) )
+ ] );
+
+ $description = new Conjunction( [
+ new ValueDescription( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ $description
+ ] );
+
+ $description = new Disjunction( [
+ $description,
+ new ClassDescription( [] )
+ ] );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php
new file mode 100644
index 00000000..9e945c8e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\Query\Language\NamespaceDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class NamespaceDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter',
+ new NamespaceDescriptionInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanBuildConditionFor() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\NamespaceDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new NamespaceDescriptionInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider namespaceProvider
+ */
+ public function testNamespaceCondition( $description, $orderByProperty, $expectedConditionType, $expectedConditionString ) {
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new NamespaceDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function namespaceProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new NamespaceDescription( NS_MAIN );
+ $orderByProperty = null;
+
+ $expected = $stringBuilder
+ ->addString( '{ ?result swivt:wikiNamespace "0"^^xsd:integer . }' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php
new file mode 100644
index 00000000..52c240a9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php
@@ -0,0 +1,552 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\Query\Language\ValueDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\SomePropertyInterpreter;
+use SMW\SPARQLStore\QueryEngine\EngineOptions;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+use SMWDITime as DITime;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\SomePropertyInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class SomePropertyInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\SomePropertyInterpreter',
+ new SomePropertyInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanInterpretDescription() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\SomeProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SomePropertyInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testSomeProperty( $description, $orderByProperty, $sortkeys, $expectedConditionType, $expectedConditionString ) {
+
+ $hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setHierarchyLookup( $hierarchyLookup );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setSortKeys( $sortkeys );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new SomePropertyInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function testHierarchyPattern() {
+
+ $engineOptions = new EngineOptions();
+ $engineOptions->set( 'smwgSparqlQFeatures', SMW_SPARQL_QF_SUBP );
+
+ $property = new DIProperty( 'Foo' );
+
+ $hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $hierarchyLookup->expects( $this->once() )
+ ->method( 'hasSubproperty' )
+ ->with( $this->equalTo( $property ) )
+ ->will( $this->returnValue( true ) );
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory, $engineOptions );
+ $conditionBuilder->setHierarchyLookup( $hierarchyLookup );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+
+ $instance = new SomePropertyInterpreter( $conditionBuilder );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $expected = UtilityFactory::getInstance()->newStringBuilder()
+ ->addString( '?result ?sp2 ?v1 .' )->addNewLine()
+ ->addString( '{ ' )->addNewLine()
+ ->addString( '?sp2 rdfs:subPropertyOf* property:Foo .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expected,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition';
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ new Disjunction()
+ );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '<http://www.example.org> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#nothing> .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 1
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ new ThingDescription()
+ );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 2 Inverse
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo', true ),
+ new ThingDescription()
+ );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?v1 property:Foo ?result .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 3
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foo'),
+ new ThingDescription()
+ );
+
+ $orderByProperty = new DIProperty( 'Foo');
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 4
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIBlob( 'SomePropertyBlobValue' ) )
+ );
+
+ $orderByProperty = null;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result property:Foo "SomePropertyBlobValue" .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 5
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIBlob( 'SomePropertyBlobValue' ) )
+ );
+
+ $orderByProperty = $property;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Foo "SomePropertyBlobValue" .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 6
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $propertyValue = new DIWikiPage( 'SomePropertyPageValue', NS_HELP );
+
+ $propertyValueName = \SMWTurtleSerializer::getTurtleNameForExpElement(
+ \SMWExporter::getInstance()->getResourceElementForWikiPage( $propertyValue )
+ );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( $propertyValue )
+ );
+
+ $orderByProperty = $property;
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( "?result property:Foo $propertyValueName ." )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 7
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIWikiPage( 'SomePropertyPageValue', NS_HELP ), $property, SMW_CMP_LEQ )
+ );
+
+ $orderByProperty = new DIProperty( 'SomePropertyPageValue' );
+ $sortkeys = [];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1sk <= "SomePropertyPageValue" )' )->addNewLine()
+ ->addString( '?v1 swivt:wikiPageSortKey ?v1sk .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 8
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIWikiPage( 'SomePropertyPageValue', NS_HELP ), $property, SMW_CMP_LEQ )
+ );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Bar' ),
+ $description
+ );
+
+ $orderByProperty = new DIProperty( 'Bar' );
+ $sortkeys = [ 'Foo' => 'ASC' ];
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Bar ?v1 .' )->addNewLine()
+ ->addString( '{ ?v1 property:Foo ?v2 .' )->addNewLine()
+ ->addString( 'FILTER( ?v2sk <= "SomePropertyPageValue" )' )->addNewLine()
+ ->addString( '?v2 swivt:wikiPageSortKey ?v2sk .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 9 Inverse -> ?v1 property:Foo ?v2 vs. ?v2 property:Foo ?v1
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( 'Foo', true );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIWikiPage( 'SomePropertyPageValue', NS_HELP ), $property, SMW_CMP_LEQ )
+ );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Bar' ),
+ $description
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Bar ?v1 .' )->addNewLine()
+ ->addString( '{ ?v2 property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v2sk <= "SomePropertyPageValue" )' )->addNewLine()
+ ->addString( '?v2 swivt:wikiPageSortKey ?v2sk .' )->addNewLine()
+ ->addString( '}' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 10
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( '_MDAT' );
+
+ $description = new SomeProperty(
+ $property,
+ new ThingDescription()
+ );
+
+ $sortkeys = [ '_MDAT' => 'ASC' ];
+ $propertyLabel = str_replace( ' ', '_', $property->getLabel() );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( "?result property:{$propertyLabel}-23aux ?v1 ." )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 11, issue 556
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = new SomeProperty(
+ $property,
+ new Disjunction( [
+ new ValueDescription( new DIBlob( 'Bar' ) ),
+ new ValueDescription( new DIBlob( 'Baz' ) )
+ ] )
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Foo ?v1 .' )->addNewLine()
+ ->addString( 'FILTER( ?v1 = "Bar" || ?v1 = "Baz" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 12 use the rdf/owl equivalent for a predefined property
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( '_SUBC' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIBlob( 'Bar' ) )
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result rdfs:subClassOf "Bar" .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 13
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( '_SUBP' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DIWikiPage( 'Bar', SMW_NS_PROPERTY ) )
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result rdfs:subPropertyOf property:Bar .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ # 14 aux-property
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\WhereCondition';
+
+ $property = new DIProperty( '_MDAT' );
+
+ $description = new SomeProperty(
+ $property,
+ new ValueDescription( new DITime( 1, 1970, 01, 01, 1, 1 ) )
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( '?result property:Modification_date-23aux "2440587.5423611"^^xsd:double .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $sortkeys,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php
new file mode 100644
index 00000000..cab64703
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DIProperty;
+use SMW\Query\Language\ThingDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ThingDescriptionInterpreter;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ThingDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ThingDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ThingDescriptionInterpreter',
+ new ThingDescriptionInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanBuildConditionFor() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ThingDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ThingDescriptionInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testThingDescriptionInterpreter( $description, $orderByProperty, $expectedConditionType, $expectedConditionString ) {
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+ $conditionBuilder->setOrderByProperty( $orderByProperty );
+
+ $instance = new ThingDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\TrueCondition';
+
+ $description = new ThingDescription();
+ $orderByProperty = null;
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected
+ ];
+
+ # 1
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\TrueCondition';
+
+ $description = new ThingDescription();
+ $orderByProperty = new DIProperty( 'Foo' );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $orderByProperty,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php
new file mode 100644
index 00000000..46b521d3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php
@@ -0,0 +1,593 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ValueDescription;
+use SMW\SPARQLStore\QueryEngine\ConditionBuilder;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter;
+use SMW\SPARQLStore\QueryEngine\EngineOptions;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob as DIBlob;
+use SMWDINumber as DINumber;
+use SMWDIUri as DIUri;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ValueDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $descriptionInterpreterFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter',
+ new ValueDescriptionInterpreter( $conditionBuilder )
+ );
+ }
+
+ public function testCanBuildConditionFor() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ValueDescriptionInterpreter( $conditionBuilder );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider notSupportedDataItemTypeProvider
+ */
+ public function testCreateFalseConditionForNotSupportedDataItemType( $dataItem ) {
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->setConstructorArgs( [ $this->descriptionInterpreterFactory ] )
+ ->setMethods( [ 'isSetFlag' ] )
+ ->getMock();
+
+ $conditionBuilder->expects( $this->once() )
+ ->method( 'isSetFlag' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new ValueDescriptionInterpreter( $conditionBuilder );
+
+ $description = new ValueDescription(
+ $dataItem,
+ null
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\Condition\FalseCondition',
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider comparatorProvider
+ */
+ public function testValueConditionForDifferentComparators( $description, $expectedConditionType, $expectedConditionString ) {
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+
+ $instance = new ValueDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ $this->assertEquals(
+ $expectedConditionString,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function testValueConditionOnRediret() {
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->setConstructorArgs( [ $this->descriptionInterpreterFactory ] )
+ ->setMethods( [ 'tryToFindRedirectVariableForDataItem' ] )
+ ->getMock();
+
+ $conditionBuilder->expects( $this->once() )
+ ->method( 'tryToFindRedirectVariableForDataItem' )
+ ->will( $this->returnValue( '?r1' ) );
+
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+
+ $instance = new ValueDescriptionInterpreter( $conditionBuilder );
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'Foo', NS_MAIN ),
+ null
+ );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $expectedConditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $this->assertInstanceOf(
+ $expectedConditionType,
+ $condition
+ );
+
+ // The redirect pattern add by conditionBuilder at th end of
+ // the mapping
+ $expected = UtilityFactory::getInstance()->newStringBuilder()
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( 'FILTER( ?result = ?r1 )' )->addNewLine()
+ ->getString();
+
+ $this->assertEquals(
+ $expected,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ /**
+ * @dataProvider noCaseDescritionProvider
+ */
+ public function testValueConditionOnNoCase( $description, $expected ) {
+
+ $engineOptions = new EngineOptions();
+ $engineOptions->set( 'smwgSparqlQFeatures', SMW_SPARQL_QF_NOCASE );
+
+ $resultVariable = 'result';
+
+ $conditionBuilder = new ConditionBuilder( $this->descriptionInterpreterFactory, $engineOptions );
+ $conditionBuilder->setResultVariable( $resultVariable );
+ $conditionBuilder->setJoinVariable( $resultVariable );
+
+ $instance = new ValueDescriptionInterpreter( $conditionBuilder );
+
+ $condition = $instance->interpretDescription( $description );
+
+ $this->assertEquals(
+ $expected,
+ $conditionBuilder->convertConditionToString( $condition )
+ );
+ }
+
+ public function comparatorProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_EQ
+ );
+
+ $expected = $stringBuilder
+ ->addString( '"SomePropertyValue" swivt:page ?url .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 1
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LESS
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( ?result < "SomePropertyValue" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 2 Less for a non-blob (DIWikiPage type) value
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'SomePropertyValuePage', NS_MAIN ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LESS
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( 'FILTER( ?resultsk < "SomePropertyValuePage" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 3
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIProperty( 'SomeProperty' ),
+ null,
+ SMW_CMP_LESS
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( ?result < property:SomeProperty )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 4
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_GRTR
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( ?result > "SomePropertyValue" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 5
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LEQ
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( ?result <= "SomePropertyValue" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 6
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_GEQ
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( ?result >= "SomePropertyValue" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 7
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_NEQ
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( ?result != "SomePropertyValue" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 8
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LIKE
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( regex( ?result, "^SomePropertyValue$", "s") )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 9
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_NLKE
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( !regex( ?result, "^SomePropertyValue$", "s") )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 10 Regex on a non-blob value
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\TrueCondition';
+
+ $description = new ValueDescription(
+ new DINumber( 42 ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_NLKE
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 11 Regex on a non-blob (DIWikiPage type) value
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition';
+
+ $description = new ValueDescription(
+ new DIWikiPage( 'SomePropertyValuePage', NS_MAIN ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LIKE
+ );
+
+ $expected = $stringBuilder
+ ->addString( 'FILTER( regex( ?v1, "^SomePropertyValuePage$", "s") )' )->addNewLine()
+ ->addString( '?result swivt:wikiPageSortKey ?v1 .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 12 Regex on a non-blob (DIUri type) value
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\FilterCondition';
+
+ $description = new ValueDescription(
+ new DIUri( 'http', '//example.org', '', '' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_LIKE
+ );
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( regex( str( ?result ), "^.*//example\\\.org$", "i") )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ # 13 Unknown comparator operator
+ $conditionType = '\SMW\SPARQLStore\QueryEngine\Condition\TrueCondition';
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $expected = $stringBuilder
+ ->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $conditionType,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+ public function noCaseDescritionProvider() {
+
+ $stringBuilder = UtilityFactory::getInstance()->newStringBuilder();
+
+ # 0
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_NLKE
+ );
+
+ $expected = $stringBuilder->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( !regex( ?result, "^SomePropertyValue$", "i") )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ # 1
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_PRIM_LIKE
+ );
+
+ $expected = $stringBuilder->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( regex( ?result, "^SomePropertyValue$", "i") )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ # 2
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_EQ
+ );
+
+ $expected = $stringBuilder->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( lcase(str(?result) ) = "somepropertyvalue" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ # 3
+ $description = new ValueDescription(
+ new DIBlob( 'SomePropertyValue' ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_NEQ
+ );
+
+ $expected = $stringBuilder->addString( '?result swivt:page ?url .' )->addNewLine()
+ ->addString( 'FILTER( lcase(str(?result) ) != "somepropertyvalue" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ # 4
+ $description = new ValueDescription(
+ new DIWikiPage( 'SomePropertyValuePage', NS_MAIN ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_EQ
+ );
+
+ $expected = $stringBuilder->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( 'FILTER( lcase(str(?resultsk) ) = "somepropertyvaluepage" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ # 5
+ $description = new ValueDescription(
+ new DIWikiPage( 'SomePropertyValuePage', NS_MAIN ),
+ new DIProperty( 'Foo' ),
+ SMW_CMP_NEQ
+ );
+
+ $expected = $stringBuilder->addString( '?result swivt:wikiPageSortKey ?resultsk .' )->addNewLine()
+ ->addString( 'FILTER( lcase(str(?resultsk) ) != "somepropertyvaluepage" )' )->addNewLine()
+ ->getString();
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+ public function notSupportedDataItemTypeProvider() {
+
+ $dataItem = $this->getMockBuilder( '\SMWDIGeoCoord' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ $dataItem
+ ];
+
+ $dataItem = $this->getMockBuilder( '\SMW\DIConcept' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ $dataItem
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/EngineOptionsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/EngineOptionsTest.php
new file mode 100644
index 00000000..8bed60ff
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/EngineOptionsTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine;
+
+use SMW\SPARQLStore\QueryEngine\EngineOptions;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\EngineOptions
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class EngineOptionsTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\EngineOptions',
+ new EngineOptions()
+ );
+ }
+
+ /**
+ * @dataProvider initialSettingsProvider
+ */
+ public function testInitialState( $setting, $expected ) {
+
+ $instance = new EngineOptions();
+
+ $this->assertNotNull(
+ $instance->get( $setting )
+ );
+ }
+
+ public function testAddOption() {
+
+ $instance = new EngineOptions();
+
+ $this->assertFalse(
+ $instance->has( 'Foo' )
+ );
+
+ $instance->set( 'Foo', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->get( 'Foo' )
+ );
+ }
+
+ public function testUnregisteredKeyThrowsException() {
+
+ $instance = new EngineOptions();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->get( 'Foo' );
+ }
+
+ public function initialSettingsProvider() {
+
+ $provider[] = [
+ 'smwgIgnoreQueryErrors',
+ 'boolean'
+ ];
+
+ $provider[] = [
+ 'smwgQSortFeatures',
+ 'integer'
+ ];
+
+ $provider[] = [
+ 'smwgQSubpropertyDepth',
+ 'integer'
+ ];
+
+ $provider[] = [
+ 'smwgQSubcategoryDepth',
+ 'integer'
+ ];
+
+ $provider[] = [
+ 'smwgSparqlQFeatures',
+ 'integer'
+ ];
+
+ return $provider;
+ }
+
+}
+
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryEngineTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryEngineTest.php
new file mode 100644
index 00000000..162fd5e2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryEngineTest.php
@@ -0,0 +1,526 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine;
+
+use SMW\SPARQLStore\QueryEngine\EngineOptions;
+use SMW\SPARQLStore\QueryEngine\QueryEngine;
+use SMW\SPARQLStore\QueryEngine\QueryResultFactory;
+use SMWQuery as Query;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\QueryEngine
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class QueryEngineTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultFactory = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\QueryResultFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\QueryEngine',
+ new QueryEngine( $connection, $conditionBuilder, $queryResultFactory )
+ );
+ }
+
+ public function testEmptyGetQueryResultWhereQueryContainsErrors() {
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $engineOptions = new EngineOptions();
+ $engineOptions->set( 'smwgIgnoreQueryErrors', false );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store ),
+ $engineOptions
+ );
+
+ $query = new Query( $description );
+ $query->addErrors( [ 'Foo' ] );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+
+ $this->assertEmpty(
+ $instance->getQueryResult( $query )->getResults()
+ );
+ }
+
+ public function testConditionBuilderReturnsErrors() {
+
+ $condition = $this->getMockForAbstractClass( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' );
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [ 'bogus-error' ] ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'getConditionFrom' )
+ ->will( $this->returnValue( $condition ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $engineOptions = new EngineOptions();
+ $engineOptions->set( 'smwgIgnoreQueryErrors', false );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store ),
+ $engineOptions
+ );
+
+ $query = new Query( $description );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+
+ $this->assertEmpty(
+ $instance->getQueryResult( $query )->getResults()
+ );
+
+ $this->assertEquals(
+ [ 'bogus-error' ],
+ $query->getErrors()
+ );
+ }
+
+ public function testEmptyGetQueryResultWhereQueryModeIsNone() {
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store )
+ );
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_NONE;
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+
+ $this->assertEmpty(
+ $instance->getQueryResult( $query )->getResults()
+ );
+ }
+
+ public function testInvalidSorkeyThrowsException() {
+
+ $sortKeys = [ 'Foo', 'Bar' ];
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $condition = $this->getMockForAbstractClass( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' );
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'setSortKeys' )
+ ->will( $this->returnValue( $conditionBuilder ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'getSortKeys' )
+ ->will( $this->returnValue( $sortKeys ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'getConditionFrom' )
+ ->will( $this->returnValue( $condition ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store )
+ );
+
+ $query = new Query( $description );
+ $query->setSortKeys( $sortKeys );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getQueryResult( $query );
+ }
+
+ public function testtestGetQueryResultForDebugQueryMode() {
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $condition = $this->getMockForAbstractClass( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' );
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'setSortKeys' )
+ ->will( $this->returnValue( $conditionBuilder ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'getConditionFrom' )
+ ->will( $this->returnValue( $condition ) );
+
+ $queryResultFactory = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\QueryResultFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine( $connection, $conditionBuilder, $queryResultFactory );
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_DEBUG;
+
+ $this->assertNotInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+ public function testGetSuccessCountQueryResultForMockedCompostion() {
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'selectCount' )
+ ->will( $this->returnValue( $repositoryResult ) );
+
+ $condition = $this->getMockForAbstractClass( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'setSortKeys' )
+ ->will( $this->returnValue( $conditionBuilder ) );
+
+ $conditionBuilder->expects( $this->once() )
+ ->method( 'getConditionFrom' )
+ ->will( $this->returnValue( $condition ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store )
+ );
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_COUNT;
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+ public function testInstanceQueryResultForMockedCompostion() {
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'select' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->once() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $repositoryResult ) );
+
+ $condition = $this->getMockForAbstractClass( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'setSortKeys' )
+ ->will( $this->returnValue( $conditionBuilder ) );
+
+ $conditionBuilder->expects( $this->once() )
+ ->method( 'getConditionFrom' )
+ ->will( $this->returnValue( $condition ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store )
+ );
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+ public function testGetImmediateEmptyQueryResultForLimitLessThanOne() {
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store = $this->getMockBuilder( '\SMW\SPARQLStore\SPARQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->never() )
+ ->method( 'setSortKeys' )
+ ->will( $this->returnValue( $conditionBuilder ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store )
+ );
+
+ $query = new Query( $description );
+ $query->setUnboundLimit( -1 );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+ public function testInstanceQueryResultForMockedSingletonCompostion() {
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'ask' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->once() )
+ ->method( 'ask' )
+ ->will( $this->returnValue( $repositoryResult ) );
+
+ $element = $this->getMockBuilder( '\SMW\Exporter\Element' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $condition = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\Condition\SingletonCondition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $condition->matchElement = $element;
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'setSortKeys' )
+ ->will( $this->returnValue( $conditionBuilder ) );
+
+ $conditionBuilder->expects( $this->once() )
+ ->method( 'getConditionFrom' )
+ ->will( $this->returnValue( $condition ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store )
+ );
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+ public function testDebugQueryResultForMockedCompostion() {
+
+ // PHPUnit 3.7 goes drumming when trying to add a method on an
+ // interface hence the use of the concrete class
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSparqlForSelect' ] )
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'getSparqlForSelect' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $condition = $this->getMockForAbstractClass( '\SMW\SPARQLStore\QueryEngine\Condition\Condition' );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $conditionBuilder = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\ConditionBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $conditionBuilder->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $conditionBuilder->expects( $this->atLeastOnce() )
+ ->method( 'setSortKeys' )
+ ->will( $this->returnValue( $conditionBuilder ) );
+
+ $conditionBuilder->expects( $this->once() )
+ ->method( 'getConditionFrom' )
+ ->will( $this->returnValue( $condition ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $connection,
+ $conditionBuilder,
+ new QueryResultFactory( $store )
+ );
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_DEBUG;
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryResultFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryResultFactoryTest.php
new file mode 100644
index 00000000..d16b9c3e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/QueryResultFactoryTest.php
@@ -0,0 +1,201 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine;
+
+use SMW\SPARQLStore\QueryEngine\QueryResultFactory;
+use SMW\Tests\Utils\Mock\IteratorMockBuilder;
+use SMWQuery as Query;
+use SMWQueryResult as QueryResult;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\QueryResultFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class QueryResultFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\QueryResultFactory',
+ new QueryResultFactory( $store )
+ );
+ }
+
+ public function testGetQueryResultObjectForNullSet() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $query = new Query( $description );
+
+ $instance = new QueryResultFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->newQueryResult( null, $query )
+ );
+ }
+
+ /**
+ * @dataProvider errorCodeProvider
+ */
+ public function testGetQueryResultObjectForCountQuery( $errorCode ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $RepositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $RepositoryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrorCode' )
+ ->will( $this->returnValue( $errorCode ) );
+
+ $description = $this->getMockBuilder( '\SMWDescription' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_COUNT;
+
+ $instance = new QueryResultFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->newQueryResult( $RepositoryResult, $query )
+ );
+
+ $this->assertQueryResultErrorCodeForCountValue(
+ $errorCode,
+ $instance->newQueryResult( $RepositoryResult, $query )
+ );
+ }
+
+ /**
+ * @dataProvider errorCodeProvider
+ */
+ public function testGetQueryResultObjectForEmptyInstanceQuery( $errorCode ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $RepositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $RepositoryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrorCode' )
+ ->will( $this->returnValue( $errorCode ) );
+
+ $description = $this->getMockBuilder( '\SMWDescription' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $instance = new QueryResultFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->newQueryResult( $RepositoryResult, $query )
+ );
+
+ $this->assertQueryResultErrorCode(
+ $errorCode,
+ $instance->newQueryResult( $RepositoryResult, $query )
+ );
+ }
+
+ /**
+ * @dataProvider errorCodeProvider
+ */
+ public function testGetQueryResultObjectForInstanceQuery( $errorCode ) {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $expElement = $this->getMockBuilder( '\SMWExpElement' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $iteratorMockBuilder = new IteratorMockBuilder();
+
+ $repositoryResult = $iteratorMockBuilder->setClass( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->with( [ [ $expElement ] ] )
+ ->getMockForIterator();
+
+ $repositoryResult->expects( $this->atLeastOnce() )
+ ->method( 'getErrorCode' )
+ ->will( $this->returnValue( $errorCode ) );
+
+ $description = $this->getMockBuilder( '\SMWDescription' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_INSTANCES;
+
+ $instance = new QueryResultFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->newQueryResult( $repositoryResult, $query )
+ );
+
+ $this->assertQueryResultErrorCode(
+ $errorCode,
+ $instance->newQueryResult( $repositoryResult, $query )
+ );
+ }
+
+ private function assertQueryResultErrorCodeForCountValue( $errorCode, QueryResult $queryResult ) {
+
+ if ( $errorCode > 0 ) {
+ $this->assertNotEmpty( $queryResult->getErrors() );
+ return $this->assertNull( $queryResult->getCountValue() );
+ }
+
+ $this->assertEmpty( $queryResult->getErrors() );
+ $this->assertInternalType( 'integer', $queryResult->getCountValue() );
+ }
+
+ private function assertQueryResultErrorCode( $errorCode, QueryResult $queryResult ) {
+
+ if ( $errorCode > 0 ) {
+ return $this->assertNotEmpty( $queryResult->getErrors() );
+ }
+
+ $this->assertEmpty( $queryResult->getErrors() );
+ }
+
+ public function errorCodeProvider() {
+
+ $provider = [
+ [ 0 ],
+ [ 1 ],
+ [ 2 ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/RepositoryResultTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/RepositoryResultTest.php
new file mode 100644
index 00000000..79655ad9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/RepositoryResultTest.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine;
+
+use SMW\SPARQLStore\QueryEngine\RepositoryResult;
+use SMWExpLiteral as ExpLiteral;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\RepositoryResult
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class RepositoryResultTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\RepositoryResult',
+ new RepositoryResult()
+ );
+
+ $this->assertInstanceOf(
+ '\Iterator',
+ new RepositoryResult()
+ );
+ }
+
+ public function testIsBooleanTrue() {
+
+ $instance = new RepositoryResult(
+ [],
+ [ [ new ExpLiteral( 'true', 'http://www.w3.org/2001/XMLSchema#boolean' ) ] ]
+ );
+
+ $this->assertEquals( 1, $instance->numRows() );
+ $this->assertTrue( $instance->isBooleanTrue() );
+ }
+
+ public function testIsBooleanNotTrue() {
+
+ $instance = new RepositoryResult();
+
+ $this->assertFalse(
+ $instance->isBooleanTrue()
+ );
+ }
+
+ public function testGetNumericValue() {
+
+ $instance = new RepositoryResult(
+ [],
+ [ [ new ExpLiteral( '2', 'http://www.w3.org/2001/XMLSchema#integer' ) ] ]
+ );
+
+ $this->assertEquals( 1, $instance->numRows() );
+ $this->assertSame( 2, $instance->getNumericValue() );
+ }
+
+ public function testGetZeroNumericValue() {
+
+ $instance = new RepositoryResult();
+
+ $this->assertSame(
+ 0,
+ $instance->getNumericValue()
+ );
+ }
+
+ public function testSetGetErrorCode() {
+
+ $instance = new RepositoryResult();
+
+ $this->assertEquals(
+ RepositoryResult::ERROR_NOERROR,
+ $instance->getErrorCode()
+ );
+
+ $instance->setErrorCode(
+ RepositoryResult::ERROR_INCOMPLETE
+ );
+
+ $this->assertEquals(
+ RepositoryResult::ERROR_INCOMPLETE,
+ $instance->getErrorCode()
+ );
+ }
+
+ public function testIteration() {
+
+ $rawList = [
+ [
+ new ExpLiteral( '2', 'http://www.w3.org/2001/XMLSchema#integer' ),
+ new ExpLiteral( 'true', 'http://www.w3.org/2001/XMLSchema#boolean' )
+ ],
+ [
+ new ExpLiteral( '2', 'http://www.w3.org/2001/XMLSchema#integer' )
+ ]
+ ];
+
+ $instance = new RepositoryResult(
+ [],
+ [ $rawList[0], $rawList[1] ]
+ );
+
+ foreach ( $instance as $key => $listItem ) {
+ $this->assertEquals( $rawList[$key], $listItem );
+ }
+ }
+
+ public function testGetComments() {
+
+ $instance = new RepositoryResult(
+ [],
+ [],
+ [ 'Foo' ]
+ );
+
+ $this->assertContains(
+ 'Foo',
+ $instance->getComments()
+ );
+ }
+
+}
+
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/XmlResponseParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/XmlResponseParserTest.php
new file mode 100644
index 00000000..30d930f1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/QueryEngine/XmlResponseParserTest.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\QueryEngine;
+
+use SMW\SPARQLStore\QueryEngine\XmlResponseParser;
+use SMW\Tests\Utils\Fixtures\Results\FakeRawResultProvider;
+use SMWExpLiteral as ExpLiteral;
+use SMWExpResource as ExpResource;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\QueryEngine\XmlResponseParser
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class XmlResponseParserTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\XmlResponseParser',
+ new XmlResponseParser()
+ );
+ }
+
+ /**
+ * @dataProvider rawXmlResultDocumentProvider
+ */
+ public function testXmlParse( $rawXmlResult, $expectedResultRowItemInstance ) {
+
+ $instance = new XmlResponseParser();
+ $resultFormat = $instance->parse( $rawXmlResult );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\RepositoryResult',
+ $resultFormat
+ );
+
+ $this->assertResultFormat(
+ $expectedResultRowItemInstance,
+ $resultFormat
+ );
+ }
+
+ public function testInvalidXmlThrowsException() {
+
+ $rawResultProvider = new FakeRawResultProvider();
+
+ $instance = new XmlResponseParser();
+
+ $this->setExpectedException( '\SMW\SPARQLStore\Exception\XmlParserException' );
+ $instance->parse( $rawResultProvider->getInvalidSparqlResultXml() );
+ }
+
+ protected function assertResultFormat( $expectedResultRowItemInstance, $results ) {
+
+ if ( !is_array( $expectedResultRowItemInstance ) ) {
+ $expectedResultRowItemInstance = [ $expectedResultRowItemInstance ];
+ }
+
+ foreach ( $results as $key => $row ) {
+ $this->assertResultRow( $expectedResultRowItemInstance[$key], $row );
+ }
+ }
+
+ protected function assertResultRow( $expectedItemInstance, $row ) {
+
+ foreach ( $row as $key => $item ) {
+
+ if ( $item === null ) {
+ continue;
+ }
+
+ $this->assertEquals( $expectedItemInstance, $item );
+ }
+ }
+
+ public function rawXmlResultDocumentProvider() {
+
+ $rawResultProvider = new FakeRawResultProvider();
+
+ #0
+ $provider[] = [
+ $rawResultProvider->getUriResourceSparqlResultXml(),
+ new ExpResource( 'http://example.org/id/Foo' )
+ ];
+
+ #1
+ $provider[] = [
+ $rawResultProvider->getEmptySparqlResultXml(),
+ null
+ ];
+
+ #2 @bug 62218
+ $provider[] = [
+ $rawResultProvider->getNonTypeLiteralResultXml(),
+ new ExpLiteral( 'Has foo' )
+ ];
+
+ #3
+ $provider[] = [
+ $rawResultProvider->getBooleanSparqlResultXml(),
+ new ExpLiteral( 'true', 'http://www.w3.org/2001/XMLSchema#boolean' )
+ ];
+
+ #4
+ $provider[] = [
+ $rawResultProvider->getStringTypeLiteralSparqlResultXml(),
+ new ExpLiteral( 'Foo', 'http://www.w3.org/2001/XMLSchema#string' )
+ ];
+
+ #5
+ $provider[] = [
+ $rawResultProvider->getIntegerTypeLiteralSparqlResultXml(),
+ new ExpLiteral( '1', 'http://www.w3.org/2001/XMLSchema#integer' )
+ ];
+
+ #6
+ $provider[] = [
+ $rawResultProvider->getMixedRowsSparqlResultXml(),
+ [
+ new ExpResource( 'http://example.org/id/Foo' ),
+ new ExpResource( 'http://example.org/id/Bar' ),
+ new ExpLiteral( 'Quux', 'http://www.w3.org/2001/XMLSchema#string' )
+ ]
+ ];
+
+ #7 #450
+ $provider[] = [
+ false,
+ null
+ ];
+
+ #8 #450
+ $provider[] = [
+ 'false',
+ null
+ ];
+
+ #9 #626
+ $provider[] = [
+ 'true',
+ new ExpLiteral( 'true', 'http://www.w3.org/2001/XMLSchema#boolean' )
+ ];
+
+ #10
+ $provider[] = [
+ '',
+ new ExpLiteral( 'false', 'http://www.w3.org/2001/XMLSchema#boolean' )
+ ];
+
+ #11
+ $provider[] = [
+ $rawResultProvider->getMixedRowsSparqlResultUtf8Xml(),
+ [
+ new ExpResource( 'http://example.org/id/F安o' ),
+ new ExpResource( 'http://example.org/id/B定ar' ),
+ new ExpLiteral( 'Quux安定', 'http://www.w3.org/2001/XMLSchema#string' )
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/ReplicationDataTruncatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/ReplicationDataTruncatorTest.php
new file mode 100644
index 00000000..4ef8f747
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/ReplicationDataTruncatorTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\DIProperty;
+use SMW\SPARQLStore\ReplicationDataTruncator;
+
+/**
+ * @covers \SMW\SPARQLStore\ReplicationDataTruncator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ReplicationDataTruncatorTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticData;
+
+ public function setUp() {
+
+ $this->semanticData = $this->getMockBuilder( '\SMW\semanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\ReplicationDataTruncator',
+ new ReplicationDataTruncator()
+ );
+ }
+
+ public function testOnEmptyList() {
+
+ $instance = new ReplicationDataTruncator();
+ $semanticData = $instance->doTruncate( $this->semanticData );
+
+ $this->assertSame(
+ $this->semanticData,
+ $semanticData
+ );
+ }
+
+ public function testOnExemptedList() {
+
+ $property = new DIProperty( 'Foo_bar' );
+
+ $this->semanticData->expects( $this->once() )
+ ->method( 'removeProperty' )
+ ->with( $this->equalTo( $property ) );
+
+ $instance = new ReplicationDataTruncator();
+ $instance->setPropertyExemptionList( [ 'Foo bar' ] );
+
+ $instance->doTruncate( $this->semanticData );
+ }
+
+ public function testOnExemptedListWithPredefinedProperty() {
+
+ $property = new DIProperty( '_ASK' );
+
+ $this->semanticData->expects( $this->once() )
+ ->method( 'removeProperty' )
+ ->with($this->equalTo( $property ) );
+
+ $instance = new ReplicationDataTruncator();
+ $instance->setPropertyExemptionList( [ 'Has query' ] );
+
+ $instance->doTruncate( $this->semanticData );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryClientTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryClientTest.php
new file mode 100644
index 00000000..38fdb133
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryClientTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\SPARQLStore\RepositoryClient;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryClient
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class RepositoryClientTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryClient',
+ new RepositoryClient( '', '', '', '' )
+ );
+ }
+
+ public function testPublicAccess() {
+
+ $instance = new RepositoryClient( 'Foo', 'Bar', 'Nu', 'Vim' );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->getDefaultGraph()
+ );
+
+ $this->assertSame(
+ 'Bar',
+ $instance->getQueryEndpoint()
+ );
+
+ $this->assertSame(
+ 'Nu',
+ $instance->getUpdateEndpoint()
+ );
+
+ $this->assertSame(
+ 'Vim',
+ $instance->getDataEndpoint()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectionProviderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectionProviderTest.php
new file mode 100644
index 00000000..5bfe5fe7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectionProviderTest.php
@@ -0,0 +1,223 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\SPARQLStore\RepositoryConnectionProvider;
+use SMW\Tests\Utils\GlobalsProvider;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryConnectionProvider
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class RepositoryConnectionProviderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $globalsProvider;
+ private $smwgSparqlCustomConnector;
+ private $smwgSparqlRepositoryConnector;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->globalsProvider = GlobalsProvider::getInstance();
+
+ $this->smwgSparqlRepositoryConnector = $this->globalsProvider->get( 'smwgSparqlRepositoryConnector' );
+ $this->smwgSparqlCustomConnector = $this->globalsProvider->get( 'smwgSparqlCustomConnector' );
+ }
+
+ protected function tearDown() {
+
+ $this->globalsProvider->set(
+ 'smwgSparqlRepositoryConnector',
+ $this->smwgSparqlRepositoryConnector
+ );
+
+ $this->globalsProvider->set(
+ 'smwgSparqlCustomConnector',
+ $this->smwgSparqlCustomConnector
+ );
+
+ $this->globalsProvider->clear();
+ }
+
+ public function testCanConstruct() {
+
+ $instance = new RepositoryConnectionProvider();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryConnectionProvider',
+ $instance
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Connection\ConnectionProvider',
+ $instance
+ );
+ }
+
+ public function testGetDefaultConnection() {
+
+ $instance = new RepositoryConnectionProvider( 'default' );
+ $instance->setHttpVersionTo( CURL_HTTP_VERSION_NONE );
+
+ $this->assertInstanceOf(
+ '\SMWSparqlDatabase',
+ $instance->getConnection()
+ );
+
+ $connection = $instance->getConnection();
+
+ $this->assertSame(
+ $connection,
+ $instance->getConnection()
+ );
+
+ $instance->releaseConnection();
+
+ $this->assertNotSame(
+ $connection,
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetFusekiConnection() {
+
+ $instance = new RepositoryConnectionProvider( 'fuSEKi' );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryConnectors\FusekiRepositoryConnector',
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetVirtuosoConnection() {
+
+ $instance = new RepositoryConnectionProvider( 'virtuoso' );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryConnectors\VirtuosoRepositoryConnector',
+ $instance->getConnection()
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ '\SMWSparqlDatabaseVirtuoso',
+ $instance->getConnection()
+ );
+ }
+
+ public function testGet4StoreConnection() {
+
+ $instance = new RepositoryConnectionProvider( '4STORE' );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryConnectors\FourstoreRepositoryConnector',
+ $instance->getConnection()
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ '\SMWSparqlDatabase4Store',
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetSesameConnection() {
+
+ $instance = new RepositoryConnectionProvider( 'sesame' );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector',
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetGenericConnection() {
+
+ $instance = new RepositoryConnectionProvider( 'generic' );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector',
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetDefaultConnectorForUnknownConnectorId() {
+
+ $this->globalsProvider->set(
+ 'smwgSparqlRepositoryConnector',
+ 'default'
+ );
+
+ $instance = new RepositoryConnectionProvider( 'foo' );
+
+ $this->assertInstanceOf(
+ '\SMWSparqlDatabase',
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetDefaultConnectorForEmptyConnectorId() {
+
+ $this->globalsProvider->set(
+ 'smwgSparqlRepositoryConnector',
+ 'default'
+ );
+
+ $instance = new RepositoryConnectionProvider();
+
+ $this->assertInstanceOf(
+ '\SMWSparqlDatabase',
+ $instance->getConnection()
+ );
+ }
+
+ public function testGetDefaultConnectorForUnMappedId() {
+
+ $this->globalsProvider->set(
+ 'smwgSparqlRepositoryConnector',
+ 'idThatCanNotBeMapped'
+ );
+
+ $instance = new RepositoryConnectionProvider();
+
+ $this->assertInstanceOf(
+ '\SMWSparqlDatabase',
+ $instance->getConnection()
+ );
+ }
+
+ public function testInvalidCustomClassConnectorThrowsException() {
+
+ $this->globalsProvider->set(
+ 'smwgSparqlCustomConnector',
+ 'InvalidCustomClassConnector'
+ );
+
+ $instance = new RepositoryConnectionProvider( 'custom' );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getConnection();
+ }
+
+ public function testInvalidCustomRespositoryConnectorThrowsException() {
+
+ $this->globalsProvider->set(
+ 'smwgSparqlCustomConnector',
+ '\SMW\Tests\Utils\Fixtures\InvalidCustomRespositoryConnector'
+ );
+
+ $instance = new RepositoryConnectionProvider( 'custom' );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getConnection();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/ElementaryRepositoryConnectorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/ElementaryRepositoryConnectorTest.php
new file mode 100644
index 00000000..e0d22e8d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/ElementaryRepositoryConnectorTest.php
@@ -0,0 +1,190 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\RepositoryConnectors;
+
+use SMW\SPARQLStore\RepositoryClient;
+use SMW\Tests\Utils\Fixtures\Results\FakeRawResultProvider;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ElementaryRepositoryConnectorTest extends \PHPUnit_Framework_TestCase {
+
+ public function getRepositoryConnectors() {
+ // Legacy and should be removed once obsolete
+ return [
+ 'SMWSparqlDatabase'
+ ];
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameForAskProvider
+ *
+ * @see https://www.w3.org/TR/rdf-sparql-query/#ask
+ */
+ public function testAskToQueryEndpointOnMockedHttpRequest( $httpDatabaseConnector, $expectedPostField ) {
+
+ $rawResultProvider = new FakeRawResultProvider();
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->at( 8 ) )
+ ->method( 'setOption' )
+ ->with(
+ $this->equalTo( CURLOPT_POSTFIELDS ),
+ $this->stringContains( $expectedPostField ) )
+ ->will( $this->returnValue( true ) );
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'execute' )
+ ->will( $this->returnValue( $rawResultProvider->getEmptySparqlResultXml() ) );
+
+ $instance = new $httpDatabaseConnector(
+ new RepositoryClient( 'http://foo/myDefaultGraph', 'http://localhost:9999/query' ),
+ $httpRequest
+ );
+
+ $repositoryResult = $instance->ask(
+ '?x foaf:name "Foo"',
+ [ 'foaf' => 'http://xmlns.com/foaf/0.1/>' ]
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\QueryEngine\RepositoryResult',
+ $repositoryResult
+ );
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameForDeleteProvider
+ *
+ * @see http://www.w3.org/TR/sparql11-update/#deleteInsert
+ */
+ public function testDeleteToUpdateEndpointOnMockedHttpRequest( $httpDatabaseConnector, $expectedPostField ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->at( 7 ) )
+ ->method( 'setOption' )
+ ->with(
+ $this->equalTo( CURLOPT_POSTFIELDS ),
+ $this->stringContains( $expectedPostField ) )
+ ->will( $this->returnValue( true ) );
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastErrorCode' )
+ ->will( $this->returnValue( 0 ) );
+
+ $instance = new $httpDatabaseConnector(
+ new RepositoryClient(
+ 'http://foo/myDefaultGraph',
+ 'http://localhost:9999/query',
+ 'http://localhost:9999/update'
+ ),
+ $httpRequest
+ );
+
+ $this->assertTrue(
+ $instance->delete( 'wiki:Foo ?p ?o', 'wiki:Foo ?p ?o' )
+ );
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameForInsertProvider
+ *
+ * @see http://www.w3.org/TR/sparql11-http-rdf-update/#http-post
+ */
+ public function testInsertViaHttpPostToDataPointOnMockedHttpRequest( $httpDatabaseConnector ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->once() )
+ ->method( 'getLastErrorCode' )
+ ->will( $this->returnValue( 0 ) );
+
+ $instance = new $httpDatabaseConnector(
+ new RepositoryClient(
+ 'http://foo/myDefaultGraph',
+ 'http://localhost:9999/query',
+ 'http://localhost:9999/update',
+ 'http://localhost:9999/data'
+ ),
+ $httpRequest
+ );
+
+ $this->assertTrue(
+ $instance->insertData( 'property:Foo wiki:Bar;' )
+ );
+ }
+
+ public function httpDatabaseConnectorInstanceNameForAskProvider() {
+
+ $provider = [];
+ $encodedDefaultGraph = urlencode( 'http://foo/myDefaultGraph' );
+
+ foreach ( $this->getRepositoryConnectors() as $repositoryConnector ) {
+
+ switch ( $repositoryConnector ) {
+ case '\SMW\SPARQLStore\RepositoryConnectors\FusekiRepositoryConnector':
+ $expectedPostField = '&default-graph-uri=' . $encodedDefaultGraph . '&output=xml';
+ break;
+ case 'SMWSparqlDatabase4Store':
+ case '\SMW\SPARQLStore\RepositoryConnectors\FourstoreRepositoryConnector':
+ $expectedPostField = "&restricted=1" . '&default-graph-uri=' . $encodedDefaultGraph;
+ break;
+ default:
+ $expectedPostField = '&default-graph-uri=' . $encodedDefaultGraph;
+ break;
+ };
+
+ $provider[] = [ $repositoryConnector, $expectedPostField ];
+ }
+
+ return $provider;
+ }
+
+ public function httpDatabaseConnectorInstanceNameForDeleteProvider() {
+
+ $provider = [];
+
+ foreach ( $this->getRepositoryConnectors() as $repositoryConnector ) {
+
+ switch ( $repositoryConnector ) {
+ case 'SMWSparqlDatabaseVirtuoso':
+ case 'SMW\SPARQLStore\RepositoryConnectors\VirtuosoRepositoryConnector':
+ $expectedPostField = 'query=';
+ break;
+ default:
+ $expectedPostField = 'update=';
+ break;
+ };
+
+ $provider[] = [ $repositoryConnector, $expectedPostField ];
+ }
+
+ return $provider;
+ }
+
+ public function httpDatabaseConnectorInstanceNameForInsertProvider() {
+
+ $provider = [];
+
+ foreach ( $this->getRepositoryConnectors() as $repositoryConnector ) {
+ $provider[] = [ $repositoryConnector ];
+ }
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FourstoreRepositoryConnectorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FourstoreRepositoryConnectorTest.php
new file mode 100644
index 00000000..00f02bb2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FourstoreRepositoryConnectorTest.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\RepositoryConnectors;
+
+use SMW\SPARQLStore\RepositoryConnectors\FourstoreRepositoryConnector;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\FourstoreRepositoryConnector
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FourstoreRepositoryConnectorTest extends ElementaryRepositoryConnectorTest {
+
+ public function getRepositoryConnectors() {
+ return [
+ 'SMWSparqlDatabase4Store',
+ FourstoreRepositoryConnector::class
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FusekiRepositoryConnectorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FusekiRepositoryConnectorTest.php
new file mode 100644
index 00000000..5e36b0cf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/FusekiRepositoryConnectorTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\RepositoryConnectors;
+
+use SMW\SPARQLStore\RepositoryConnectors\FusekiRepositoryConnector;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\FusekiRepositoryConnector
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FusekiRepositoryConnectorTest extends ElementaryRepositoryConnectorTest {
+
+ public function getRepositoryConnectors() {
+ return [
+ FusekiRepositoryConnector::class
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/GenericRepositoryConnectorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/GenericRepositoryConnectorTest.php
new file mode 100644
index 00000000..7a5fcafe
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/GenericRepositoryConnectorTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\RepositoryConnectors;
+
+use SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class GenericRepositoryConnectorTest extends ElementaryRepositoryConnectorTest {
+
+ public function getRepositoryConnectors() {
+ return [
+ GenericRepositoryConnector::class
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/RepositoryConnectorsExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/RepositoryConnectorsExceptionTest.php
new file mode 100644
index 00000000..eea9843d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/RepositoryConnectorsExceptionTest.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\RepositoryConnectors;
+
+use SMW\SPARQLStore\RepositoryClient;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\FusekiRepositoryConnector
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\FourstoreRepositoryConnector
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\VirtuosoRepositoryConnector
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector
+ *
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class RepositoryConnectorsExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $defaultGraph;
+
+ private $databaseConnectors = [
+ '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector',
+ '\SMW\SPARQLStore\RepositoryConnectors\FusekiRepositoryConnector',
+ '\SMW\SPARQLStore\RepositoryConnectors\FourstoreRepositoryConnector',
+ '\SMW\SPARQLStore\RepositoryConnectors\VirtuosoRepositoryConnector',
+
+ // Legacy and should be removed once obsolete
+ 'SMWSparqlDatabase4Store',
+ 'SMWSparqlDatabaseVirtuoso',
+ 'SMWSparqlDatabase'
+ ];
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->defaultGraph = 'http://foo/myDefaultGraph';
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameProvider
+ */
+ public function testCanConstruct( $httpConnector ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector',
+ new $httpConnector( new RepositoryClient( $this->defaultGraph, '' ), $httpRequest )
+ );
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameProvider
+ */
+ public function testDoQueryForEmptyQueryEndpointThrowsException( $httpConnector ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new $httpConnector(
+ new RepositoryClient( $this->defaultGraph, '' ),
+ $httpRequest
+ );
+
+ $this->setExpectedException( '\SMW\SPARQLStore\Exception\BadHttpEndpointResponseException' );
+ $instance->doQuery( '' );
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameProvider
+ */
+ public function testDoUpdateForEmptyUpdateEndpointThrowsException( $httpConnector ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new $httpConnector(
+ new RepositoryClient( $this->defaultGraph, '', '' ),
+ $httpRequest
+ );
+
+ $this->setExpectedException( '\SMW\SPARQLStore\Exception\BadHttpEndpointResponseException' );
+ $instance->doUpdate( '' );
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameProvider
+ */
+ public function testDoHttpPostForEmptyDataEndpointThrowsException( $httpConnector ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new $httpConnector(
+ new RepositoryClient( $this->defaultGraph, '', '', '' ),
+ $httpRequest
+ );
+
+ $this->setExpectedException( '\SMW\SPARQLStore\Exception\BadHttpEndpointResponseException' );
+ $instance->doHttpPost( '' );
+ }
+
+ /**
+ * @dataProvider httpDatabaseConnectorInstanceNameProvider
+ */
+ public function testDoHttpPostForUnreachableDataEndpointThrowsException( $httpConnector ) {
+
+ $httpRequest = $this->getMockBuilder( '\Onoi\HttpRequest\HttpRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $httpRequest->expects( $this->atLeastOnce() )
+ ->method( 'getLastErrorCode' )
+ ->will( $this->returnValue( 22 ) );
+
+ $instance = new $httpConnector(
+ new RepositoryClient( $this->defaultGraph, '', '', 'unreachableDataEndpoint' ),
+ $httpRequest
+ );
+
+ $this->setExpectedException( 'Exception' );
+ $instance->doHttpPost( '' );
+ }
+
+ public function httpDatabaseConnectorInstanceNameProvider() {
+
+ $provider = [];
+
+ foreach ( $this->databaseConnectors as $databaseConnector ) {
+ $provider[] = [ $databaseConnector ];
+ }
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/VirtuosoRepositoryConnectorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/VirtuosoRepositoryConnectorTest.php
new file mode 100644
index 00000000..3395f66b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryConnectors/VirtuosoRepositoryConnectorTest.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore\RepositoryConnectors;
+
+use SMW\SPARQLStore\RepositoryConnectors\VirtuosoRepositoryConnector;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryConnectors\VirtuosoRepositoryConnector
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class VirtuosoRepositoryConnectorTest extends ElementaryRepositoryConnectorTest {
+
+ public function getRepositoryConnectors() {
+ return [
+ 'SMWSparqlDatabaseVirtuoso',
+ VirtuosoRepositoryConnector::class
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryRedirectLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryRedirectLookupTest.php
new file mode 100644
index 00000000..ed5d9546
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/RepositoryRedirectLookupTest.php
@@ -0,0 +1,292 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\DIWikiPage;
+use SMW\Exporter\Escaper;
+use SMW\InMemoryPoolCache;
+use SMW\SPARQLStore\RepositoryRedirectLookup;
+use SMWExpLiteral as ExpLiteral;
+use SMWExpNsResource as ExpNsResource;
+use SMWExporter as Exporter;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SPARQLStore\RepositoryRedirectLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class RepositoryRedirectLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $repositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryRedirectLookup',
+ new RepositoryRedirectLookup( $repositoryConnection )
+ );
+ }
+
+ public function testRedirectTargetForBlankNode() {
+
+ $repositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+
+ $expNsResource = new ExpNsResource( '', '', '', null );
+ $exists = null;
+
+ $this->assertSame(
+ $expNsResource,
+ $instance->findRedirectTargetResource( $expNsResource, $exists )
+ );
+
+ $this->assertFalse( $exists );
+ }
+
+ public function testRedirectTargetForDataItemWithSubobject() {
+
+ $repositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+ $dataItem = new DIWikiPage( 'Foo', 1, '', 'beingASubobject' );
+
+ $expNsResource = new ExpNsResource( 'Foo', 'Bar', '', $dataItem );
+ $exists = null;
+
+ $this->assertSame(
+ $expNsResource,
+ $instance->findRedirectTargetResource( $expNsResource, $exists )
+ );
+
+ $this->assertTrue( $exists );
+ }
+
+ public function testRedirectTargetForDBLookupWithNoEntry() {
+
+ $repositoryConnection = $this->createRepositoryConnectionMockToUse( false );
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+ $dataItem = new DIWikiPage( 'Foo', 1, '', '' );
+
+ $expNsResource = new ExpNsResource( 'Foo', 'Bar', '', $dataItem );
+ $exists = null;
+
+ $this->assertSame(
+ $expNsResource,
+ $instance->findRedirectTargetResource( $expNsResource, $exists )
+ );
+
+ $this->assertFalse( $exists );
+ }
+
+ public function testRedirectTargetForDBLookupWithSingleEntry() {
+
+ $expLiteral = new ExpLiteral( 'Redirect' );
+
+ $repositoryConnection = $this->createRepositoryConnectionMockToUse( [ $expLiteral ] );
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+ $instance->reset();
+
+ $dataItem = new DIWikiPage( 'Foo', 1, '', '' );
+
+ $expNsResource = new ExpNsResource( 'Foo', 'Bar', '', $dataItem );
+ $exists = null;
+
+ $this->assertSame(
+ $expNsResource,
+ $instance->findRedirectTargetResource( $expNsResource, $exists )
+ );
+
+ $this->assertTrue( $exists );
+ }
+
+ public function testRedirectTargetForDBLookupWithMultipleEntries() {
+
+ $expLiteral = new ExpLiteral( 'Redirect' );
+
+ $repositoryConnection = $this->createRepositoryConnectionMockToUse( [ $expLiteral, null ] );
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+ $instance->reset();
+
+ $dataItem = new DIWikiPage( 'Foo', 1, '', '' );
+
+ $expNsResource = new ExpNsResource( 'Foo', 'Bar', '', $dataItem );
+ $exists = null;
+
+ $this->assertSame(
+ $expNsResource,
+ $instance->findRedirectTargetResource( $expNsResource, $exists )
+ );
+
+ $this->assertTrue( $exists );
+ }
+
+ public function testRedirectTargetForDBLookupWithMultipleEntriesForcesNewResource() {
+
+ $propertyPage = new DIWikiPage( 'Foo', SMW_NS_PROPERTY );
+
+ $resource = new ExpNsResource(
+ 'Foo',
+ Exporter::getInstance()->getNamespaceUri( 'property' ),
+ 'property',
+ $propertyPage
+ );
+
+ $repositoryConnection = $this->createRepositoryConnectionMockToUse( [ $resource, $resource ] );
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+ $instance->reset();
+
+ $dataItem = new DIWikiPage( 'Foo', 1, '', '' );
+
+ $expNsResource = new ExpNsResource( 'Foo', 'Bar', '', $dataItem );
+ $exists = null;
+
+ $targetResource = $instance->findRedirectTargetResource( $expNsResource, $exists );
+
+ $this->assertNotSame(
+ $expNsResource,
+ $targetResource
+ );
+
+ $expectedResource = new ExpNsResource(
+ Escaper::encodePage( $propertyPage ),
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'wiki'
+ );
+
+ $this->assertEquals(
+ $expectedResource,
+ $targetResource
+ );
+
+ $this->assertTrue( $exists );
+ }
+
+ public function testRedirectTargetForDBLookupWithForNonMultipleResourceEntryThrowsException() {
+
+ $expLiteral = new ExpLiteral( 'Redirect' );
+
+ $repositoryConnection = $this->createRepositoryConnectionMockToUse( [ $expLiteral, $expLiteral ] );
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+ $instance->reset();
+
+ $dataItem = new DIWikiPage( 'Foo', 1, '', '' );
+
+ $expNsResource = new ExpNsResource( 'Foo', 'Bar', '', $dataItem );
+ $exists = null;
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->findRedirectTargetResource( $expNsResource, $exists );
+ }
+
+ public function testRedirectTargetForCachedLookup() {
+
+ $dataItem = new DIWikiPage( 'Foo', NS_MAIN );
+ $expNsResource = new ExpNsResource( 'Foo', 'Bar', '', $dataItem );
+
+ $poolCache = InMemoryPoolCache::getInstance()->getPoolCacheById( RepositoryRedirectLookup::POOLCACHE_ID );
+
+ $poolCache->save(
+ $expNsResource->getUri(),
+ $expNsResource
+ );
+
+ $repositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+
+ $exists = null;
+
+ $instance->findRedirectTargetResource( $expNsResource, $exists );
+
+ $this->assertTrue( $exists );
+ $instance->reset();
+ }
+
+ /**
+ * @dataProvider nonRedirectableResourceProvider
+ */
+ public function testRedirectTargetForNonRedirectableResource( $expNsResource ) {
+
+ $repositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new RepositoryRedirectLookup( $repositoryConnection );
+ $instance->reset();
+
+ $exists = null;
+
+ $instance->findRedirectTargetResource( $expNsResource, $exists );
+ $instance->reset();
+
+ $this->assertFalse( $exists );
+ }
+
+ private function createRepositoryConnectionMockToUse( $listReturnValue ) {
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $repositoryResult->expects( $this->once() )
+ ->method( 'current' )
+ ->will( $this->returnValue( $listReturnValue ) );
+
+ $repositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $repositoryConnection->expects( $this->once() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $repositoryResult ) );
+
+ return $repositoryConnection;
+ }
+
+ public function nonRedirectableResourceProvider() {
+
+ $provider[] = [
+ Exporter::getInstance()->getSpecialPropertyResource( '_INST' )
+ ];
+
+ $provider[] = [
+ Exporter::getInstance()->getSpecialPropertyResource( '_SUBC' )
+ ];
+
+ $provider[] = [
+ Exporter::getInstance()->getSpecialPropertyResource( '_REDI' )
+ ];
+
+ $provider[] = [
+ Exporter::getInstance()->getSpecialPropertyResource( '_MDAT' )
+ ];
+
+ $provider[] = [
+ Exporter::getInstance()->getSpecialPropertyResource( '_MDAT', true )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreFactoryTest.php
new file mode 100644
index 00000000..3253cd01
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreFactoryTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\SPARQLStore\SPARQLStoreFactory;
+
+/**
+ * @covers \SMW\SPARQLStore\SPARQLStoreFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class SPARQLStoreFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $repositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SPARQLStore\SPARQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $repositoryConnection ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\SPARQLStoreFactory',
+ new SPARQLStoreFactory( $this->store )
+ );
+ }
+
+ public function testCanConstructBaseStore() {
+
+ $instance = new SPARQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMWSQLStore3',
+ $instance->getBaseStore( 'SMWSQLStore3' )
+ );
+ }
+
+ public function testCanConstructMasterQueryEngine() {
+
+ $instance = new SPARQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\QueryEngine',
+ $instance->newMasterQueryEngine()
+ );
+ }
+
+ public function testCanConstructConnectionManager() {
+
+ $instance = new SPARQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\Connection\ConnectionManager',
+ $instance->getConnectionManager()
+ );
+ }
+
+ public function testCanConstructRepositoryRedirectLookup() {
+
+ $instance = new SPARQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\RepositoryRedirectLookup',
+ $instance->newRepositoryRedirectLookup()
+ );
+ }
+
+ public function testCanConstructReplicationDataTruncator() {
+
+ $instance = new SPARQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\ReplicationDataTruncator',
+ $instance->newReplicationDataTruncator()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreTest.php
new file mode 100644
index 00000000..20407192
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/SPARQLStoreTest.php
@@ -0,0 +1,358 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SPARQLStore\SPARQLStore;
+use SMW\Subobject;
+use SMW\Tests\TestEnvironment;
+use SMWExporter as Exporter;
+use SMWTurtleSerializer as TurtleSerializer;
+use Title;
+
+/**
+ * @covers \SMW\SPARQLStore\SPARQLStore
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class SPARQLStoreTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+
+ protected function setUp() {
+ parent::setup();
+
+ $testEnvironment = new TestEnvironment();
+ $this->semanticDataFactory = $testEnvironment->getUtilityFactory()->newSemanticDataFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\SPARQLStore',
+ new SPARQLStore()
+ );
+
+ // Legacy
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\SPARQLStore',
+ new \SMWSPARQLStore()
+ );
+ }
+
+ public function testGetSemanticDataOnMockBaseStore() {
+
+ $subject = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $baseStore = $this->getMockBuilder( '\SMWStore' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $baseStore->expects( $this->once() )
+ ->method( 'getSemanticData' )
+ ->with( $this->equalTo( $subject ) )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $instance = new SPARQLStore( $baseStore );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $instance->getSemanticData( $subject )
+ );
+ }
+
+ public function testDeleteSubjectOnMockBaseStore() {
+
+ $title = Title::newFromText( 'DeleteSubjectOnMockBaseStore' );
+
+ $expResource = Exporter::getInstance()->getDataItemExpElement( DIWikiPage::newFromTitle( $title ) );
+ $resourceUri = TurtleSerializer::getTurtleNameForExpElement( $expResource );
+
+ $extraNamespaces = [
+ $expResource->getNamespaceId() => $expResource->getNamespace()
+ ];
+
+ $baseStore = $this->getMockBuilder( '\SMWStore' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $baseStore->expects( $this->once() )
+ ->method( 'deleteSubject' )
+ ->with( $this->equalTo( $title ) )
+ ->will( $this->returnValue( true ) );
+
+ $sparqlDatabase = $this->getMockBuilder( '\SMWSparqlDatabase' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $sparqlDatabase->expects( $this->once() )
+ ->method( 'deleteContentByValue' )
+ ->will( $this->returnValue( true ) );
+
+ $sparqlDatabase->expects( $this->once() )
+ ->method( 'delete' )
+ ->with(
+ $this->equalTo( "{$resourceUri} ?p ?o" ),
+ $this->equalTo( "{$resourceUri} ?p ?o" ),
+ $this->equalTo( $extraNamespaces ) )
+ ->will( $this->returnValue( true ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $sparqlDatabase ) );
+
+ $instance = new SPARQLStore( $baseStore );
+ $instance->setConnectionManager( $connectionManager );
+
+ $instance->deleteSubject( $title );
+ }
+
+ public function testDoSparqlDataUpdateOnMockBaseStore() {
+
+ $semanticData = new SemanticData( new DIWikiPage( __METHOD__, NS_MAIN ) );
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( 'Foo' ),
+ $semanticData->getSubject()
+ );
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $baseStore = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $sparqlDatabase = $this->getMockBuilder( '\SMWSparqlDatabase' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $sparqlDatabase->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $repositoryResult ) );
+
+ $sparqlDatabase->expects( $this->once() )
+ ->method( 'insertData' );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $sparqlDatabase ) );
+
+ $instance = new SPARQLStore( $baseStore );
+ $instance->setConnectionManager( $connectionManager );
+
+ $instance->doSparqlDataUpdate( $semanticData );
+ }
+
+ public function testCallToChangeTitleForCompletePageMove() {
+
+ $oldTitle = Title::newFromText( __METHOD__ . '-old' );
+ $newTitle = Title::newFromText( __METHOD__ . '-new' );
+
+ $respositoryConnection = $this->getMockBuilder( '\SMW\SPARQLStore\RespositoryConnection' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'insertDelete' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'changeTitle' );
+
+ $instance = $this->getMockBuilder( '\SMW\SPARQLStore\SPARQLStore' )
+ ->setConstructorArgs( [ $store ] )
+ ->setMethods( [ 'doSparqlDataDelete', 'getConnection' ] )
+ ->getMock();
+
+ $instance->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $respositoryConnection ) );
+
+ $instance->expects( $this->once() )
+ ->method( 'doSparqlDataDelete' )
+ ->with( $this->equalTo( DIWikiPage::newFromTitle( $oldTitle ) ) );
+
+ $instance->changeTitle( $oldTitle, $newTitle, 42, 0 );
+ }
+
+ public function testNoDeleteTaskForSubobjectsDuringUpdate() {
+
+ $expectedSubjectForDeleteTask = DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) );
+
+ $subobject = new Subobject( $expectedSubjectForDeleteTask->getTitle() );
+ $subobject->setEmptyContainerForId( 'Foo' );
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( $expectedSubjectForDeleteTask )
+ ->newEmptySemanticData();
+
+ $semanticData->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $repositoryResult = $this->getMockBuilder( '\SMW\SPARQLStore\QueryEngine\RepositoryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnectors\GenericRepositoryConnector' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $repositoryResult ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'insertData' );
+
+ $instance = $this->getMockBuilder( '\SMW\SPARQLStore\SPARQLStore' )
+ ->setMethods( [ 'doSparqlDataDelete', 'getConnection' ] )
+ ->getMock();
+
+ $instance->expects( $this->once() )
+ ->method( 'doSparqlDataDelete' )
+ ->with( $this->equalTo( $expectedSubjectForDeleteTask ) );
+
+ $instance->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance->doSparqlDataUpdate( $semanticData );
+ }
+
+ public function testGetQueryResult() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getPrintrequests' )
+ ->will( $this->returnValue( [] ) );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $idLookup = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'warmUpCache' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idLookup ) );
+
+ $repositoryClient = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryClient' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'getRepositoryClient' )
+ ->will( $this->returnValue( $repositoryClient ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SPARQLStore( $store );
+ $instance->setConnectionManager( $connectionManager );
+
+ $instance->getQueryResult( $query );
+ }
+
+ public function testGetQueryResultOnDisabledQueryEndpoint() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->once() )
+ ->method( 'getQueryResult' );
+
+ $repositoryClient = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryClient' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $repositoryClient->expects( $this->atLeastOnce() )
+ ->method( 'getQueryEndpoint' )
+ ->will( $this->returnValue( false ) );
+
+ $connection = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryConnection' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'getRepositoryClient' )
+ ->will( $this->returnValue( $repositoryClient ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SPARQLStore( $store );
+ $instance->setConnectionManager( $connectionManager );
+
+ $instance->getQueryResult( $query );
+ }
+
+ public function testGetPropertyTableIdReferenceFinder() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyTableIdReferenceFinder' );
+
+ $instance = new SPARQLStore( $store );
+ $instance->getPropertyTableIdReferenceFinder();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/TurtleTriplesBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/TurtleTriplesBuilderTest.php
new file mode 100644
index 00000000..e7777a45
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SPARQLStore/TurtleTriplesBuilderTest.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace SMW\Tests\SPARQLStore;
+
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SPARQLStore\TurtleTriplesBuilder;
+use SMWExpNsResource as ExpNsResource;
+use SMWExporter as Exporter;
+
+/**
+ * @covers \SMW\SPARQLStore\TurtleTriplesBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class TurtleTriplesBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $repositoryRedirectLookup;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->repositoryRedirectLookup = $this->getMockBuilder( '\SMW\SPARQLStore\RepositoryRedirectLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SPARQLStore\TurtleTriplesBuilder',
+ new TurtleTriplesBuilder( $this->repositoryRedirectLookup )
+ );
+ }
+
+ public function testBuildTriplesForEmptySemanticDataContainer() {
+
+ $expNsResource = new ExpNsResource(
+ 'Redirect',
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'Redirect'
+ );
+
+ $semanticData = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN, '' )
+ );
+
+ $this->repositoryRedirectLookup->expects( $this->atLeastOnce() )
+ ->method( 'findRedirectTargetResource' )
+ ->will( $this->returnValue( $expNsResource ) );
+
+ $instance = new TurtleTriplesBuilder(
+ $this->repositoryRedirectLookup
+ );
+
+ $instance->doBuildTriplesFrom( $semanticData );
+
+ $this->assertTrue(
+ $instance->hasTriples()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getTriples()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getPrefixes()
+ );
+ }
+
+ public function testChunkedTriples() {
+
+ $expNsResource = new ExpNsResource(
+ 'Redirect',
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'Redirect'
+ );
+
+ $semanticData = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $this->repositoryRedirectLookup->expects( $this->atLeastOnce() )
+ ->method( 'findRedirectTargetResource' )
+ ->will( $this->returnValue( $expNsResource ) );
+
+ $instance = new TurtleTriplesBuilder(
+ $this->repositoryRedirectLookup
+ );
+
+ $instance->setTriplesChunkSize( 1 );
+ $instance->doBuildTriplesFrom( $semanticData );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getChunkedTriples()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeDiffTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeDiffTest.php
new file mode 100644
index 00000000..a9c99e58
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeDiffTest.php
@@ -0,0 +1,163 @@
+<?php
+
+namespace SMW\Tests\SQLStore\ChangeOp;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\ChangeOp\ChangeDiff;
+
+/**
+ * @covers \SMW\SQLStore\ChangeOp\ChangeDiff
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangeDiffTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ChangeDiff::class,
+ new ChangeDiff( DIWikiPage::newFromText( 'Foo' ), [], [], [] )
+ );
+ }
+
+ public function testGetSubject() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+ $instance = new ChangeDiff(
+ $subject,
+ [],
+ [],
+ []
+ );
+
+ $this->assertEquals(
+ $subject,
+ $instance->getSubject()
+ );
+ }
+
+ public function testGetPropertyList() {
+
+ $instance = new ChangeDiff(
+ DIWikiPage::newFromText( 'Foo' ),
+ [],
+ [],
+ [ 'Foo' => 42 ]
+ );
+
+ $this->assertEquals(
+ [ 'Foo' => 42 ],
+ $instance->getPropertyList()
+ );
+
+ $this->assertEquals(
+ [ 42 => 'Foo' ],
+ $instance->getPropertyList( true )
+ );
+ }
+
+ public function testGetPropertyList_SortById() {
+
+ $instance = new ChangeDiff(
+ DIWikiPage::newFromText( 'Foo' ),
+ [],
+ [],
+ [ 'Foo' => [ '_id' => 42, '_type' => '_foo' ] ]
+ );
+
+ $this->assertEquals(
+ [ 42 => [ '_key' => 'Foo', '_type' => '_foo' ] ],
+ $instance->getPropertyList( 'id' )
+ );
+ }
+
+ public function testSave() {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableChangeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\TableChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ChangeDiff(
+ DIWikiPage::newFromText( 'Foo' ),
+ [ $tableChangeOp ],
+ [],
+ [ 'Foo' => 42 ]
+ );
+
+ $cache->expects( $this->once() )
+ ->method( 'save' )
+ ->with(
+ $this->stringContains( ChangeDiff::CACHE_NAMESPACE ),
+ $this->equalTo( $instance->serialize() ) );
+
+ $instance->save( $cache );
+ }
+
+ public function testFetch() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableChangeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\TableChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ChangeDiff(
+ DIWikiPage::newFromText( 'Foo' ),
+ [ $tableChangeOp ],
+ [],
+ [ 'Foo' => 42 ]
+ );
+
+ $cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( $instance->serialize() ) );
+
+ $this->assertEquals(
+ $instance,
+ ChangeDiff::fetch( $cache, $subject )
+ );
+ }
+
+ public function testChangeList() {
+
+ $instance = new ChangeDiff(
+ DIWikiPage::newFromText( 'Foo' ),
+ [],
+ [],
+ []
+ );
+
+ $instance->setChangeList( 'Foo', [ '42', 1001 ] );
+
+ $this->assertEquals(
+ [ '42', 1001 ],
+ $instance->getChangeListByType( 'Foo' )
+ );
+ }
+
+ public function FetchFromCache() {
+
+ $changeDiff = ChangeDiff::fetch(
+ \SMW\ApplicationFactory::getInstance()->getCache(),
+ DIWikiPage::newFromText( 'DifferentSort' )
+ );
+
+ $this->assertInstanceOf(
+ ChangeDiff::class,
+ $changeDiff
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeOpTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeOpTest.php
new file mode 100644
index 00000000..8aea75da
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/ChangeOpTest.php
@@ -0,0 +1,412 @@
+<?php
+
+namespace SMW\Tests\SQLStore\ChangeOp;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\ChangeOp\ChangeOp;
+
+/**
+ * @covers \SMW\SQLStore\ChangeOp\ChangeOp
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class ChangeOpTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ChangeOp::class,
+ new ChangeOp()
+ );
+ }
+
+ public function testSerialize() {
+
+ $instance = new ChangeOp(
+ DIWikiPage::newFromText( __METHOD__ ),
+ []
+ );
+
+ $data = serialize( $instance );
+
+ $this->assertInstanceOf(
+ ChangeOp::class,
+ unserialize( $data )
+ );
+ }
+
+ /**
+ * @dataProvider diffDataProvider
+ */
+ public function testDiff( $diff, $fixedPropertyRecord, $expectedOrdered, $expectedList ) {
+
+ $instance = new ChangeOp(
+ DIWikiPage::newFromText( __METHOD__ ),
+ $diff
+ );
+
+ $instance->addFixedPropertyRecord(
+ $fixedPropertyRecord[0],
+ $fixedPropertyRecord[1]
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getFixedPropertyRecords()
+ );
+
+ $this->assertEquals(
+ $expectedOrdered,
+ $instance->getOrderedDiffByTable()
+ );
+
+ $this->assertEquals(
+ $expectedList,
+ $instance->getChangedEntityIdSummaryList()
+ );
+ }
+
+ public function testGetTableChangeOps() {
+
+ $diff = [
+ 0 => [
+ 'insert' => [
+ 'smw_di_number' => [
+ 0 => [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '123',
+ 'o_sortkey' => '123',
+ ],
+ 1 => [
+ 's_id' => 3668,
+ 'p_id' => 62,
+ 'o_serialized' => '1234',
+ 'o_sortkey' => '1234',
+ ],
+ ],
+ 'smw_fpt_mdat' => [
+ 0 => [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/28/39',
+ 'o_sortkey' => '2457250.8948958',
+ ],
+ ],
+ ],
+ 'delete' => [
+ 'smw_di_number' => [],
+ 'smw_fpt_mdat' => [],
+ ]
+ ]
+ ];
+
+ $instance = new ChangeOp(
+ DIWikiPage::newFromText( __METHOD__ ),
+ $diff
+ );
+
+ $this->assertCount(
+ 1,
+ $instance->getTableChangeOps( 'smw_di_number' )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTableChangeOps()
+ );
+ }
+
+ public function testGetListOfChangedEntitiesByType() {
+
+ $diff = [
+ 0 => [
+ 'insert' => [
+ 'smw_di_number' => [
+ 0 => [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '123',
+ 'o_sortkey' => '123',
+ ],
+ 1 => [
+ 's_id' => 3668,
+ 'p_id' => 62,
+ 'o_serialized' => '1234',
+ 'o_sortkey' => '1234',
+ ],
+ ],
+ 'smw_fpt_mdat' => [
+ 0 => [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/28/39',
+ 'o_sortkey' => '2457250.8948958',
+ ],
+ ],
+ ],
+ 'delete' => [
+ 'smw_di_number' => [],
+ 'smw_fpt_mdat' => [
+ 0 => [
+ 's_id' => 3667,
+ 'o_serialized' => '1/2015/8/16/9/28/39',
+ 'o_sortkey' => '2457250.8948958',
+ ]
+ ],
+ ]
+ ]
+ ];
+
+ $instance = new ChangeOp(
+ DIWikiPage::newFromText( __METHOD__ ),
+ $diff
+ );
+
+ $this->assertEquals(
+ [
+ 3667 => true
+ ],
+ $instance->getChangedEntityIdListByType( $instance::OP_DELETE )
+ );
+
+ $this->assertEquals(
+ [
+ 61 => true,
+ 3668 => true,
+ 62 => true
+ ],
+ $instance->getChangedEntityIdListByType( $instance::OP_INSERT )
+ );
+ }
+
+ public function testTryToGetTableChangeOpForSingleTable() {
+
+ $diff = [];
+
+ $instance = new ChangeOp(
+ DIWikiPage::newFromText( __METHOD__ ),
+ $diff
+ );
+
+ $this->assertEmpty(
+ $instance->getTableChangeOps( 'smw_di_number' )
+ );
+ }
+
+ public function testGetHash() {
+
+ $diff = [];
+
+ $instance = new ChangeOp(
+ DIWikiPage::newFromText( __METHOD__ ),
+ $diff
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHash()
+ );
+ }
+
+ public function diffDataProvider() {
+
+ $provider[] = [
+ [],
+ [ 'foo', [] ],
+ [],
+ [],
+ ];
+
+ // Insert
+ $provider[] = [
+ [
+ 0 => [
+ 'insert' => [
+ 'smw_di_number' =>
+ [ 0 => [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '123',
+ 'o_sortkey' => '123',
+ ],
+ ],
+ 'smw_fpt_mdat' =>
+ [ 0 => [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/28/39',
+ 'o_sortkey' => '2457250.8948958',
+ ],
+ ],
+ ],
+ 'delete' => [
+ 'smw_di_number' =>
+ [],
+ 'smw_fpt_mdat' =>
+ [],
+ ],
+ ],
+ ],
+ [
+ 'smw_fpt_mdat',
+ [
+ 'key' => '_MDAT',
+ 'p_id' => 29,
+ ],
+ ],
+ [
+ 'smw_di_number' => [
+ 'insert' =>
+ [ 0 => [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '123',
+ 'o_sortkey' => '123',
+ ],
+ ],
+ ],
+ 'smw_fpt_mdat' => [
+ 'property' =>
+ [
+ 'key' => '_MDAT',
+ 'p_id' => 29,
+ ],
+ 'insert' => [
+ 0 => [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/28/39',
+ 'o_sortkey' => '2457250.8948958',
+ ],
+ ],
+ ],
+ ],
+ [
+ 0 => 61,
+ 1 => 3668,
+ 2 => 29,
+ ]
+ ];
+
+ // Insert / Delete
+ $provider[] = [
+ [
+ 0 =>
+ [
+ 'insert' =>
+ [
+ 'smw_di_number' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '1001',
+ 'o_sortkey' => '1001',
+ ],
+ ],
+ 'smw_fpt_mdat' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/56/53',
+ 'o_sortkey' => '2457250.9145023',
+ ],
+ ],
+ ],
+ 'delete' =>
+ [
+ 'smw_di_number' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '123',
+ 'o_sortkey' => '123',
+ ],
+ ],
+ 'smw_fpt_mdat' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/28/39',
+ 'o_sortkey' => '2457250.8948958',
+ ],
+ ],
+ ],
+ ],
+ ],
+ [
+ 'smw_fpt_mdat',
+ [
+ 'key' => '_MDAT',
+ 'p_id' => 29,
+ ],
+ ],
+ [
+ 'smw_di_number' =>
+ [
+ 'insert' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '1001',
+ 'o_sortkey' => '1001',
+ ],
+ ],
+ 'delete' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'p_id' => 61,
+ 'o_serialized' => '123',
+ 'o_sortkey' => '123',
+ ],
+ ],
+ ],
+ 'smw_fpt_mdat' =>
+ [
+ 'property' =>
+ [
+ 'key' => '_MDAT',
+ 'p_id' => 29,
+ ],
+ 'insert' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/56/53',
+ 'o_sortkey' => '2457250.9145023',
+ ],
+ ],
+ 'delete' =>
+ [
+ 0 =>
+ [
+ 's_id' => 3668,
+ 'o_serialized' => '1/2015/8/16/9/28/39',
+ 'o_sortkey' => '2457250.8948958',
+ ],
+ ],
+ ],
+ ],
+ [
+ 0 => 61,
+ 1 => 3668,
+ 2 => 29,
+ ]
+ ];
+
+ return $provider;
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/FieldChangeOpTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/FieldChangeOpTest.php
new file mode 100644
index 00000000..690084c8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/FieldChangeOpTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace SMW\Tests\SQLStore\ChangeOp;
+
+use SMW\SQLStore\ChangeOp\FieldChangeOp;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\ChangeOp\FieldChangeOp
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class FieldChangeOpTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ FieldChangeOp::class,
+ new FieldChangeOp()
+ );
+ }
+
+ public function testChangeOp() {
+
+ $op = [
+ 's_id' => 462,
+ 'o_serialized' => '1/2016/6/10/2/3/31/0',
+ 'o_sortkey' => '2457549.5857755',
+ ];
+
+ $instance = new FieldChangeOp(
+ $op
+ );
+
+ $this->assertFalse(
+ $instance->has( 'foo' )
+ );
+
+ $this->assertSame(
+ '1/2016/6/10/2/3/31/0',
+ $instance->get( 'o_serialized' )
+ );
+
+ $instance->set( 'foo', 'bar' );
+
+ $this->assertSame(
+ 'bar',
+ $instance->get( 'foo' )
+ );
+ }
+
+ public function testInvalidGetRequestThrowsException() {
+
+ $instance = new FieldChangeOp();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->get( 'o_serialized' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php
new file mode 100644
index 00000000..cc5b2857
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangeOp/TableChangeOpTest.php
@@ -0,0 +1,226 @@
+<?php
+
+namespace SMW\Tests\SQLStore\ChangeOp;
+
+use SMW\SQLStore\ChangeOp\TableChangeOp;
+
+/**
+ * @covers \SMW\SQLStore\ChangeOp\TableChangeOp
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class TableChangeOpTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TableChangeOp::class,
+ new TableChangeOp( 'foo', [] )
+ );
+ }
+
+ public function testEmptyOps() {
+
+ $diff = [];
+
+ $instance = new TableChangeOp(
+ 'foo',
+ $diff
+ );
+
+ $this->assertSame(
+ 'foo',
+ $instance->getTableName()
+ );
+
+ $this->assertFalse(
+ $instance->isFixedPropertyOp()
+ );
+
+ $this->assertFalse(
+ $instance->hasChangeOp( TableChangeOp::OP_INSERT )
+ );
+
+ $this->assertNull(
+ $instance->getFixedPropertyValueBy( 'key' )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getFieldChangeOps( 'insert' )
+ );
+ }
+
+ public function testFixedPropertyOps() {
+
+ $diff = [
+ 'property' =>
+ [
+ 'key' => '_MDAT',
+ 'p_id' => 29,
+ ],
+ 'insert' =>
+ [
+ 0 =>
+ [
+ 's_id' => 462,
+ 'o_serialized' => '1/2016/6/10/2/3/31/0',
+ 'o_sortkey' => '2457549.5857755',
+ ],
+ ],
+ 'delete' =>
+ [
+ 0 =>
+ [
+ 's_id' => 462,
+ 'o_serialized' => '1/2016/6/10/2/1/0/0',
+ 'o_sortkey' => '2457549.5840278',
+ ],
+ ],
+ ];
+
+ $instance = new TableChangeOp(
+ 'foo',
+ $diff
+ );
+
+ $this->assertSame(
+ 'foo',
+ $instance->getTableName()
+ );
+
+ $this->assertTrue(
+ $instance->isFixedPropertyOp()
+ );
+
+ $this->assertTrue(
+ $instance->hasChangeOp( TableChangeOp::OP_INSERT )
+ );
+
+ $this->assertSame(
+ '_MDAT',
+ $instance->getFixedPropertyValueBy( 'key' )
+ );
+ }
+
+ public function testGetFieldChangeOpsNoType() {
+
+ $diff = [
+ 'property' =>
+ [
+ 'key' => '_MDAT',
+ 'p_id' => 29,
+ ],
+ 'insert' =>
+ [
+ 0 =>
+ [
+ 's_id' => 462,
+ 'o_serialized' => '1/2016/6/10/2/3/31/0',
+ 'o_sortkey' => '2457549.5857755',
+ ],
+ ],
+ 'delete' =>
+ [
+ 0 =>
+ [
+ 's_id' => 462,
+ 'o_serialized' => '1/2016/6/10/2/1/0/0',
+ 'o_sortkey' => '2457549.5840278',
+ ],
+ [
+ 's_id' => 42,
+ 'p_id' => 1001,
+ 'o_id' => 9999
+ ]
+ ]
+ ];
+
+ $instance = new TableChangeOp(
+ 'foo',
+ $diff
+ );
+
+ $this->assertCount(
+ 3,
+ $instance->getFieldChangeOps()
+ );
+
+ $this->assertCount(
+ 1,
+ $instance->getFieldChangeOps( TableChangeOp::OP_INSERT )
+ );
+
+ $this->assertCount(
+ 2,
+ $instance->getFieldChangeOps( TableChangeOp::OP_DELETE )
+ );
+
+ $this->assertCount(
+ 2,
+ $instance->getFieldChangeOps( null, [ 's_id' => [ 42 => true ] ] )
+ );
+ }
+
+ public function testFieldChangeOps_WithNoOperation() {
+
+ $diff = [
+ [
+ 's_id' => 462,
+ 'o_serialized' => '1/2016/6/10/2/1/0/0',
+ 'o_sortkey' => '2457549.5840278',
+ ],
+ [
+ 's_id' => 42,
+ 'p_id' => 1001,
+ 'o_id' => 9999
+ ]
+ ];
+
+ $instance = new TableChangeOp(
+ 'foo',
+ $diff
+ );
+
+ $this->assertCount(
+ 2,
+ $instance->getFieldChangeOps()
+ );
+
+ $this->assertCount(
+ 1,
+ $instance->getFieldChangeOps( null, [ 's_id' => [ 42 => true ] ] )
+ );
+ }
+
+ public function testToArray() {
+
+ $diff = [
+ [
+ 's_id' => 462,
+ 'o_serialized' => '1/2016/6/10/2/1/0/0',
+ 'o_sortkey' => '2457549.5840278',
+ ],
+ [
+ 's_id' => 42,
+ 'p_id' => 1001,
+ 'o_id' => 9999
+ ]
+ ];
+
+ $instance = new TableChangeOp(
+ 'foo',
+ $diff
+ );
+
+ $this->assertSame(
+ ['foo' => $diff ],
+ $instance->toArray()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangePropagationEntityFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangePropagationEntityFinderTest.php
new file mode 100644
index 00000000..dad6fefb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ChangePropagationEntityFinderTest.php
@@ -0,0 +1,185 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SQLStore\ChangePropagationEntityFinder;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\ChangePropagationEntityFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ChangePropagationEntityFinderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $iteratorFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->iteratorFactory = $this->getMockBuilder( '\SMW\IteratorFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->appendIterator = $this->getMockBuilder( '\SMW\Iterators\AppendIterator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ChangePropagationEntityFinder::class,
+ new ChangePropagationEntityFinder( $this->store, $this->iteratorFactory )
+ );
+ }
+
+ public function testFindByProperty() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $this->iteratorFactory->expects( $this->any() )
+ ->method( 'newAppendIterator' )
+ ->will( $this->returnValue( $this->appendIterator ) );
+
+ $instance = new ChangePropagationEntityFinder(
+ $this->store,
+ $this->iteratorFactory
+ );
+
+ $this->assertInstanceOf(
+ 'Iterator',
+ $instance->findByProperty( $property )
+ );
+ }
+
+ public function testFindByProperty_TypePropagation() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $this->iteratorFactory->expects( $this->any() )
+ ->method( 'newAppendIterator' )
+ ->will( $this->returnValue( $this->appendIterator ) );
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher->expects( $this->any() )
+ ->method( 'getDefaultDataItemTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $entityIdManager = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID', 'getDataItemPoolHashListFor' ] )
+ ->getMock();
+
+ $entityIdManager->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $entityIdManager->expects( $this->any() )
+ ->method( 'getDataItemPoolHashListFor' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $entityIdManager ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $instance = new ChangePropagationEntityFinder(
+ $store,
+ $this->iteratorFactory
+ );
+
+ $instance->isTypePropagation( true );
+
+ $res = $instance->findByProperty( $property );
+
+ $this->assertInstanceOf(
+ 'Iterator',
+ $res
+ );
+
+ $this->assertEquals(
+ $res,
+ $instance->findAll( $property )
+ );
+ }
+
+ public function testFindByCategory() {
+
+ $category = new DIWikiPage( 'Foo', NS_CATEGORY );
+
+ $this->iteratorFactory->expects( $this->any() )
+ ->method( 'newAppendIterator' )
+ ->will( $this->returnValue( $this->appendIterator ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( new DIProperty( '_INST' ) ),
+ $this->anything() )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( new DIProperty( '_SUBC' ) ) )
+ ->will( $this->returnValue( [ DIWikiPage::newFromText( 'Bar' ) ] ) );
+
+ $instance = new ChangePropagationEntityFinder(
+ $store,
+ $this->iteratorFactory
+ );
+
+ $res = $instance->findByCategory( $category );
+
+ $this->assertInstanceOf(
+ 'Iterator',
+ $res
+ );
+
+ $this->assertEquals(
+ $res,
+ $instance->findAll( $category )
+ );
+ }
+
+ public function testFindAllOnUnknownTypeThrowsException() {
+
+ $instance = new ChangePropagationEntityFinder(
+ $this->store,
+ $this->iteratorFactory
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->findAll( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ConceptCacheTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ConceptCacheTest.php
new file mode 100644
index 00000000..e7c32c00
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/ConceptCacheTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\ConceptCache;
+use Title;
+
+/**
+ * @covers \SMW\SQLStore\ConceptCache
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ConceptCacheTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $conceptQuerySegmentBuilder;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->conceptQuerySegmentBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\ConceptQuerySegmentBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\ConceptCache',
+ new ConceptCache( $this->store, $this->conceptQuerySegmentBuilder )
+ );
+ }
+
+ public function testRefreshConceptCache() {
+
+ $this->conceptQuerySegmentBuilder->expects( $this->once() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new ConceptCache(
+ new \SMWSQLStore3(),
+ $this->conceptQuerySegmentBuilder
+ );
+
+ $instance->refreshConceptCache(
+ Title::newFromText( 'Foo', SMW_NS_CONCEPT )
+ );
+ }
+
+ public function testDeleteConceptCache() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'delete' );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store = new \SMWSQLStore3();
+ $store->setConnectionManager( $connectionManager );
+
+ $instance = new ConceptCache(
+ $store,
+ $this->conceptQuerySegmentBuilder
+ );
+
+ $instance->deleteConceptCache(
+ Title::newFromText( 'Foo', SMW_NS_CONCEPT )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityRebuildDispatcherTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityRebuildDispatcherTest.php
new file mode 100644
index 00000000..15583175
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityRebuildDispatcherTest.php
@@ -0,0 +1,239 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\ApplicationFactory;
+use SMW\SQLStore\EntityRebuildDispatcher;
+use SMW\SQLStore\SQLStore;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\EntityRebuildDispatcher
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class EntityRebuildDispatcherTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $titleFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment(
+ [
+ 'smwgSemanticsEnabled' => true,
+ 'smwgAutoRefreshSubject' => true,
+ 'smwgCacheType' => 'hash',
+ 'smwgEnableUpdateJobs' => false,
+ ]
+ );
+
+ $jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->titleFactory = $this->getMockBuilder( '\SMW\MediaWiki\TitleFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $jobQueue );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'exists' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( 0 ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityRebuildDispatcher',
+ new EntityRebuildDispatcher( $store, $this->titleFactory )
+ );
+ }
+
+ /**
+ * @dataProvider idProvider
+ */
+ public function testDispatchRebuildForSingleIteration( $id, $expected ) {
+
+ $this->titleFactory->expects( $this->any() )
+ ->method( 'newFromIDs' )
+ ->will( $this->returnValue( [] ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'selectField' )
+ ->will( $this->returnValue( $expected ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new EntityRebuildDispatcher(
+ $store,
+ $this->titleFactory
+ );
+
+ $instance->setDispatchRangeLimit( 1 );
+ $instance->setOptions(
+ [
+ 'shallow-update' => true,
+ 'use-job' => false
+ ]
+ );
+
+ $instance->rebuild( $id );
+
+ $this->assertSame(
+ $expected,
+ $id
+ );
+
+ $this->assertLessThanOrEqual(
+ 1,
+ $instance->getEstimatedProgress()
+ );
+ }
+
+ public function testRevisionMode() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( NS_MAIN ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->titleFactory->expects( $this->any() )
+ ->method( 'newFromIDs' )
+ ->will( $this->returnValue( [ $title ] ) );
+
+ $row = [
+ 'smw_id' => 9999999999999999,
+ 'smw_title' => 'Foo',
+ 'smw_namespace' => 0,
+ 'smw_iw' => '',
+ 'smw_subobject' => '',
+ 'smw_proptable_hash' => [],
+ 'smw_rev' => 0
+ ];
+
+ $idTable = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $idTable->expects( $this->once() )
+ ->method( 'findAssociatedRev' )
+ ->with( $this->equalTo( 'Foo' ) )
+ ->will( $this->returnValue( 1001 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ (object)$row] ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'selectField' )
+ ->will( $this->returnValue( 500 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $instance = new EntityRebuildDispatcher(
+ $store,
+ $this->titleFactory
+ );
+
+ $instance->setDispatchRangeLimit( 1 );
+ $instance->setOptions(
+ [
+ 'revision-mode' => true,
+ 'force-update' => false,
+ 'use-job' => false
+ ]
+ );
+
+ $id = 999999999;
+
+ $instance->rebuild( $id );
+ }
+
+ public function idProvider() {
+
+ $provider[] = [
+ 42, // Within the border Id
+ 43
+ ];
+
+ $provider[] = [
+ 9999999999999999999,
+ -1
+ ];
+
+ return $provider;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingEntityLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingEntityLookupTest.php
new file mode 100644
index 00000000..465084f9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingEntityLookupTest.php
@@ -0,0 +1,387 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SQLStore\EntityStore\CachingEntityLookup;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\CachingEntityLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class CachingEntityLookupTest extends \PHPUnit_Framework_TestCase {
+
+ private $entityLookup;
+ private $redirectTargetLookup;
+ private $blobStore;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->entityLookup = $this->getMockBuilder( '\SMW\EntityLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->redirectTargetLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\RedirectTargetLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore = $this->getMockBuilder( '\Onoi\BlobStore\BlobStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CachingEntityLookup::class,
+ new CachingEntityLookup( $this->entityLookup, $this->redirectTargetLookup, $this->blobStore )
+ );
+ }
+
+ public function testGetSemanticDataFromFallbackForDisabledFeature() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $this->entityLookup->expects( $this->once() )
+ ->method( 'getSemanticData' )
+ ->with(
+ $this->equalTo( $subject ),
+ $this->anything() );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getReader' ] )
+ ->getMock();
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->setLookupFeatures( SMW_VL_PL );
+ $instance->getSemanticData( $subject );
+ }
+
+ public function testGetSemanticDataFromFallbackForDisabledBlobStore() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $this->entityLookup->expects( $this->once() )
+ ->method( 'getSemanticData' )
+ ->with(
+ $this->equalTo( $subject ),
+ $this->anything() );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->getSemanticData( $subject );
+ }
+
+ public function testGetSemanticDataFromFallbackForNonAvailableContainer() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'setOption' )
+ ->with(
+ $this->equalTo( $semanticData::OPT_LAST_MODIFIED ),
+ $this->anything() );
+
+ $this->entityLookup->expects( $this->once() )
+ ->method( 'getSemanticData' )
+ ->with(
+ $this->equalTo( $subject ),
+ $this->anything() )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( false ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->exactly( 2 ) )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $this->blobStore->expects( $this->exactly( 2 ) )
+ ->method( 'save' );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->setLookupFeatures( SMW_VL_SD );
+ $instance->getSemanticData( $subject );
+ }
+
+ public function testGetSemanticDataFromCacheForAvailableHash() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+ $filter = false;
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->once() )
+ ->method( 'get' )
+ ->with($this->stringContains( 'sd:' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->setLookupFeatures( SMW_VL_SD );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getSemanticData( $subject, $filter )
+ );
+ }
+
+ public function testGetPropertiesFromCacheForAvailableHash() {
+
+ $expected = [
+ new DIProperty( 'Bar' )
+ ];
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $this->redirectTargetLookup->expects( $this->once() )
+ ->method( 'findRedirectTarget' )
+ ->will( $this->returnValue( new DIProperty( 'Bar' ) ) );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->once() )
+ ->method( 'get' )
+ ->with($this->stringContains( 'pl:' ) )
+ ->will( $this->returnValue( $expected ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->setLookupFeatures( SMW_VL_PL );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getProperties( $subject )
+ );
+ }
+
+ public function testGetPropertyValuesFromCacheForAvailableHash() {
+
+ $expected = [
+ new DIWikiPage( 'Bar', NS_MAIN )
+ ];
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $this->redirectTargetLookup->expects( $this->once() )
+ ->method( 'findRedirectTarget' )
+ ->will( $this->returnValue( new DIWikiPage( 'Bar', NS_MAIN ) ) );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->once() )
+ ->method( 'get' )
+ ->with($this->stringContains( 'pv:' ) )
+ ->will( $this->returnValue( $expected ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->setLookupFeatures( SMW_VL_PV );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getPropertyValues( $subject, new DIProperty( 'Foobar' ) )
+ );
+ }
+
+ public function testGetPropertySubjectsFromCacheForAvailableHash() {
+
+ $expected = [
+ new DIWikiPage( 'Bar', NS_MAIN )
+ ];
+
+ $dataItem = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $this->redirectTargetLookup->expects( $this->never() )
+ ->method( 'findRedirectTarget' );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->once() )
+ ->method( 'get' )
+ ->with($this->stringContains( 'ps:' ) )
+ ->will( $this->returnValue( $expected ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->setLookupFeatures( SMW_VL_PS );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getPropertySubjects( new DIProperty( 'Foobar' ), $dataItem )
+ );
+ }
+
+ public function tesClearCache() {
+
+ $subject = new DIWikiPage( 'Foobar', NS_MAIN, '', 'abc' );
+
+ $semanticData = new SemanticData( $subject );
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_REDI' ),
+ new DIWikiPage( 'Bar', NS_MAIN )
+ );
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects( $this->at( 0 ) )
+ ->method( 'has' )
+ ->with( $this->stringContains( 'sd:' ) )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->at( 1 ) )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'sd:' ) )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $container->expects( $this->at( 2 ) )
+ ->method( 'has' )
+ ->with( $this->stringContains( 'list' ) )
+ ->will( $this->returnValue( true ) );
+
+ $container->expects( $this->at( 3 ) )
+ ->method( 'get' )
+ ->with( $this->stringContains( 'list' ) )
+ ->will( $this->returnValue( [ 'abc', '123' ] ) );
+
+ $this->blobStore->expects( $this->any() )
+ ->method( 'canUse' )
+ ->will( $this->returnValue( true ) );
+
+ $this->blobStore->expects( $this->atLeastOnce() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $this->blobStore->expects( $this->exactly( 4 ) )
+ ->method( 'delete' );
+
+ $instance = new CachingEntityLookup(
+ $this->entityLookup,
+ $this->redirectTargetLookup,
+ $this->blobStore
+ );
+
+ $instance->setLookupFeatures( SMW_VL_SD );
+ $instance->invalidateCache( $subject );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingSemanticDataLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingSemanticDataLookupTest.php
new file mode 100644
index 00000000..3cd22427
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/CachingSemanticDataLookupTest.php
@@ -0,0 +1,238 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\EntityStore\CachingSemanticDataLookup;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\CachingSemanticDataLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CachingSemanticDataLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $connection;
+ private $semanticDataLookup;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->semanticDataLookup = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\SemanticDataLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function tearDown() {
+ CachingSemanticDataLookup::clear();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ CachingSemanticDataLookup::class,
+ new CachingSemanticDataLookup( $this->semanticDataLookup )
+ );
+ }
+
+ public function testInitLookupCache() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $stubSemanticData = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\StubSemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stubSemanticData->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'newStubSemanticData' )
+ ->will( $this->returnValue( $stubSemanticData ) );
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $instance->initLookupCache( 42, $subject );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\StubSemanticData',
+ $instance->getSemanticDataById( 42 )
+ );
+ }
+
+ public function testUninitializedGetSemanticDataByIdThrowsException() {
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->getSemanticDataById( 42 );
+ }
+
+ public function testSetLookupCache() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'newStubSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'getTableUsageInfo' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $instance->setLookupCache( 42, $semanticData );
+
+ $this->assertEquals(
+ $semanticData,
+ $instance->getSemanticDataById( 42 )
+ );
+ }
+
+ public function testGetOptionsFromConstraint() {
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'newRequestOptions' );
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $instance->newRequestOptions( $propertyTableDefinition, $property );
+ }
+
+ public function testFetchSemanticData() {
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'fetchSemanticData' );
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $instance->fetchSemanticData( 42, null, $propertyTableDefinition );
+ }
+
+ public function testGetSemanticDataFromTable_Uncached() {
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $requestOptions = $this->getMockBuilder( '\SMW\RequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'getSemanticData' );
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $instance->getSemanticDataFromTable( 42, null, $propertyTableDefinition, $requestOptions );
+ }
+
+ public function testGetSemanticDataFromTable_FreshFetch() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stubSemanticData = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\StubSemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stubSemanticData->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'newStubSemanticData' )
+ ->will( $this->returnValue( $stubSemanticData ) );
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'fetchSemanticData' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $instance->getSemanticDataFromTable( 42, $subject, $propertyTableDefinition );
+ }
+
+ public function testGetSemanticDataFromTable_FromStaticCache() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDefinition->expects( $this->once() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( '__foo__' ) );
+
+ $stubSemanticData = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\StubSemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $stubSemanticData->expects( $this->atLeastOnce() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'newStubSemanticData' )
+ ->will( $this->returnValue( $stubSemanticData ) );
+
+ $this->semanticDataLookup->expects( $this->once() )
+ ->method( 'getTableUsageInfo' )
+ ->will( $this->returnValue( [ '__foo__' => true ] ) );
+
+ $this->semanticDataLookup->expects( $this->never() )
+ ->method( 'fetchSemanticData' );
+
+ $instance = new CachingSemanticDataLookup(
+ $this->semanticDataLookup
+ );
+
+ $instance->invalidateCache( 42 );
+ $instance->setLookupCache( 42, $stubSemanticData );
+
+ $instance->getSemanticDataFromTable( 42, $subject, $propertyTableDefinition );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIBlobHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIBlobHandlerTest.php
new file mode 100644
index 00000000..c2e7b637
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIBlobHandlerTest.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore\DIHandlers;
+
+use SMW\SQLStore\EntityStore\DIHandlers\DIBlobHandler;
+use SMW\SQLStore\TableBuilder\FieldType;
+use SMWDIBlob as DIBlob;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\DIHandlers\DIBlobHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DIBlobHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ DIBlobHandler::class,
+ new DIBlobHandler( $this->store )
+ );
+ }
+
+ public function testImmutableMethodAccess() {
+
+ $instance = new DIBlobHandler(
+ $this->store
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTableFields()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getFetchFields()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTableIndexes()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getIndexField()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getLabelField()
+ );
+ }
+
+ public function testMutableMethodAccess() {
+
+ $blob = new DIBlob( 'Foo' );
+
+ $instance = new DIBlobHandler(
+ $this->store
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getWhereConds( $blob )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getInsertValues( $blob )
+ );
+ }
+
+ /**
+ * @dataProvider fieldTypeProvider
+ */
+ public function testMutableOnFieldTypeFeature( $fieldTypeFeatures, $expected ) {
+
+ $instance = new DIBlobHandler(
+ $this->store
+ );
+
+ $instance->setFieldTypeFeatures(
+ $fieldTypeFeatures
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getTableFields()
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getFetchFields()
+ );
+ }
+
+ public function testMutableInsertValuesOnVariableLength() {
+
+ $instance = new DIBlobHandler( $this->store );
+
+ $s72 = 'zcqaBHr1jV7mINGovktU8bD6zYjgKMqfaCxQlPcT4J6h4197dQpSW5PK5f8HigRk0yEsLC2F';
+ $blob = new DIBlob( $s72 );
+
+ $expected = [
+ 'o_blob' => '',
+ 'o_hash' => $blob->getString()
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getInsertValues( $blob )
+ );
+
+ $s73 = 'zcqaBHr1jV7mINGovktU8bD6zYjgKMqfaCxQlPcT4J6h4197dQpSW5PK5f8HigRk0yEsLC2Fs';
+ $blob = new DIBlob( $s73 );
+
+ $expected = [
+ 'o_blob' => $blob->getString(),
+ 'o_hash' => 'zcqaBHr1jV7mINGovktU8bD6zYjgKMqfaCxQlPcTcf085df3633862a2d74e393fa84944e2'
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getInsertValues( $blob )
+ );
+ }
+
+ /**
+ * @dataProvider dbKeysProvider
+ */
+ public function testDataItemFromDBKeys( $dbKeys ) {
+
+ $instance = new DIBlobHandler(
+ $this->store
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIBlob',
+ $instance->dataItemFromDBKeys( $dbKeys )
+ );
+ }
+
+ /**
+ * @dataProvider dbKeysExceptionProvider
+ */
+ public function testDataItemFromDBKeysThrowsException( $dbKeys ) {
+
+ $instance = new DIBlobHandler(
+ $this->store
+ );
+
+ $this->setExpectedException( '\SMW\SQLStore\EntityStore\Exception\DataItemHandlerException' );
+ $instance->dataItemFromDBKeys( $dbKeys );
+ }
+
+ public function dbKeysProvider() {
+
+ $provider[] = [
+ [ 'Foo', '' ]
+ ];
+
+ $provider[] = [
+ [ '', 'Foo' ]
+ ];
+
+ return $provider;
+ }
+
+ public function dbKeysExceptionProvider() {
+
+ $provider[] = [
+ [ '' ]
+ ];
+
+ return $provider;
+ }
+
+ private function createRandomString( $length = 10 ) {
+ return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
+ }
+
+ public function fieldTypeProvider() {
+
+ $provider[] = [
+ SMW_FIELDT_NONE,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_hash' => FieldType::FIELD_TITLE
+ ]
+ ];
+
+ $provider[] = [
+ SMW_FIELDT_CHAR_NOCASE,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_hash' => FieldType::TYPE_CHAR_NOCASE
+ ]
+ ];
+
+ $provider[] = [
+ SMW_FIELDT_CHAR_LONG,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_hash' => FieldType::TYPE_CHAR_LONG
+ ]
+ ];
+
+ $provider[] = [
+ SMW_FIELDT_CHAR_NOCASE | SMW_FIELDT_CHAR_LONG,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_hash' => FieldType::TYPE_CHAR_LONG_NOCASE
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIUriHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIUriHandlerTest.php
new file mode 100644
index 00000000..c10afebe
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIUriHandlerTest.php
@@ -0,0 +1,215 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore\DIHandlers;
+
+use SMW\SQLStore\EntityStore\DIHandlers\DIUriHandler;
+use SMW\SQLStore\TableBuilder\FieldType;
+use SMWDIUri as DIUri;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\DIHandlers\DIUriHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DIUriHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ DIUriHandler::class,
+ new DIUriHandler( $this->store )
+ );
+ }
+
+ public function testImmutableMethodAccess() {
+
+ $instance = new DIUriHandler(
+ $this->store
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTableFields()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getFetchFields()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTableIndexes()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getIndexField()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getLabelField()
+ );
+ }
+
+ public function testMutableMethodAccess() {
+
+ $uri = new DIUri( 'http', 'example.org', '', '' );
+
+ $instance = new DIUriHandler(
+ $this->store
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getWhereConds( $uri )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getInsertValues( $uri )
+ );
+ }
+
+ /**
+ * @dataProvider fieldTypeProvider
+ */
+ public function testMutableOnFieldTypeFeature( $fieldTypeFeatures, $expected ) {
+
+ $instance = new DIUriHandler(
+ $this->store
+ );
+
+ $instance->setFieldTypeFeatures(
+ $fieldTypeFeatures
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getTableFields()
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getFetchFields()
+ );
+ }
+
+ /**
+ * @dataProvider dbKeysProvider
+ */
+ public function testDataItemFromDBKeys( $dbKeys ) {
+
+ $instance = new DIUriHandler(
+ $this->store
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIUri',
+ $instance->dataItemFromDBKeys( $dbKeys )
+ );
+ }
+
+ /**
+ * @dataProvider dbKeysExceptionProvider
+ */
+ public function testDataItemFromDBKeysThrowsException( $dbKeys ) {
+
+ $instance = new DIUriHandler(
+ $this->store
+ );
+
+ $this->setExpectedException( '\SMW\SQLStore\EntityStore\Exception\DataItemHandlerException' );
+ $instance->dataItemFromDBKeys( $dbKeys );
+ }
+
+ public function dbKeysProvider() {
+
+ $provider[] = [
+ [ 'http://example.org', '' ]
+ ];
+
+ $provider[] = [
+ [ '', 'http://example.org' ]
+ ];
+
+ return $provider;
+ }
+
+ public function dbKeysExceptionProvider() {
+
+ $provider[] = [
+ [ '' ]
+ ];
+
+ return $provider;
+ }
+
+ public function fieldTypeProvider() {
+
+ $provider[] = [
+ SMW_FIELDT_NONE,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_serialized' => FieldType::FIELD_TITLE
+ ]
+ ];
+
+ $provider[] = [
+ SMW_FIELDT_CHAR_NOCASE,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_serialized' => FieldType::TYPE_CHAR_NOCASE
+ ]
+ ];
+
+ $provider[] = [
+ SMW_FIELDT_CHAR_LONG,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_serialized' => FieldType::TYPE_CHAR_LONG
+ ]
+ ];
+
+ $provider[] = [
+ SMW_FIELDT_CHAR_NOCASE | SMW_FIELDT_CHAR_LONG,
+ [
+ 'o_blob' => FieldType::TYPE_BLOB,
+ 'o_serialized' => FieldType::TYPE_CHAR_LONG_NOCASE
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIWikiPageHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIWikiPageHandlerTest.php
new file mode 100644
index 00000000..2c5fd535
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DIHandlers/DIWikiPageHandlerTest.php
@@ -0,0 +1,165 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore\DIHandlers;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\EntityStore\DIHandlers\DIWikiPageHandler;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\DIHandlers\DIWikiPageHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DIWikiPageHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\DIHandlers\DIWikiPageHandler',
+ new DIWikiPageHandler( $store )
+ );
+ }
+
+ public function testImmutableMethodAccess() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DIWikiPageHandler( $store );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTableFields()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getFetchFields()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTableIndexes()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getIndexField()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getLabelField()
+ );
+ }
+
+ public function testMutableMethodAccess() {
+
+ // EntityIdTable
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPageID', 'makeSMWPageID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $idTable->expects( $this->any() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 1001 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $instance = new DIWikiPageHandler( $store );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getWhereConds( DIWikiPage::newFromText( 'Foo' ) )
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getInsertValues( DIWikiPage::newFromText( 'Foo' ) )
+ );
+ }
+
+ /**
+ * @dataProvider dbKeysProvider
+ */
+ public function testDataItemFromDBKeys( $dbKeys ) {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DIWikiPageHandler( $store );
+
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $instance->dataItemFromDBKeys( $dbKeys )
+ );
+ }
+
+ /**
+ * @dataProvider dbKeysExceptionProvider
+ */
+ public function testDataItemFromDBKeysThrowsException( $dbKeys ) {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DIWikiPageHandler( $store );
+
+ $this->setExpectedException( '\SMW\SQLStore\EntityStore\Exception\DataItemHandlerException' );
+ $instance->dataItemFromDBKeys( $dbKeys );
+ }
+
+ public function dbKeysProvider() {
+
+ #0 SMW_NS_PROPERTY, user defined property
+ $provider[] = [
+ [ 'Foo', SMW_NS_PROPERTY, 'bar', '', '' ]
+ ];
+
+ #1 SMW_NS_PROPERTY, pre-defined property
+ $provider[] = [
+ [ '_Foo', SMW_NS_PROPERTY, 'bar', '', '' ]
+ ];
+
+ #0 SMW_NS_PROPERTY, pre-defined property (see bug 48711)
+ $provider[] = [
+ [ '_Foo', SMW_NS_PROPERTY, '', '', '' ]
+ ];
+
+ return $provider;
+ }
+
+ public function dbKeysExceptionProvider() {
+
+ $provider[] = [
+ [ 'Foo' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DataItemHandlerDispatcherTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DataItemHandlerDispatcherTest.php
new file mode 100644
index 00000000..2aca3edf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/DataItemHandlerDispatcherTest.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\SQLStore\EntityStore\DataItemHandlerDispatcher;
+use SMWDataItem as DataItem;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\DataItemHandlerDispatcher
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DataItemHandlerDispatcherTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\DataItemHandlerDispatcher',
+ new DataItemHandlerDispatcher( $store )
+ );
+ }
+
+ /**
+ * @dataProvider dataItemTypeProvider
+ */
+ public function testGetHandlerByType( $type, $expected ) {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataItemHandlerDispatcher( $store );
+
+ $this->assertInstanceOf(
+ $expected,
+ $instance->getHandlerByType( $type )
+ );
+ }
+
+ /**
+ * @dataProvider invalidTypeProvider
+ */
+ public function testGetHandlerByInvalidTypeThrowsException( $type ) {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DataItemHandlerDispatcher( $store );
+
+ $this->setExpectedException( 'SMW\SQLStore\EntityStore\Exception\DataItemHandlerException' );
+ $instance->getHandlerByType( $type );
+ }
+
+ public function dataItemTypeProvider() {
+
+ $provider[] = [
+ DataItem::TYPE_NUMBER,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DINumberHandler'
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_BLOB,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DIBlobHandler'
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_BOOLEAN,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DIBooleanHandler'
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_URI,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DIUriHandler'
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_TIME,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DITimeHandler'
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_GEO,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DIGeoCoordinateHandler'
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_WIKIPAGE,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DIWikiPageHandler'
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_CONCEPT,
+ '\SMW\SQLStore\EntityStore\DIHandlers\DIConceptHandler'
+ ];
+
+ return $provider;
+ }
+
+ public function invalidTypeProvider() {
+
+ $provider[] = [
+ DataItem::TYPE_PROPERTY,
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_CONTAINER,
+ ];
+
+ $provider[] = [
+ DataItem::TYPE_ERROR,
+ ];
+
+ $provider[] = [
+ 'Foo',
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdCacheManagerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdCacheManagerTest.php
new file mode 100644
index 00000000..112ca5dc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdCacheManagerTest.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use Onoi\Cache\FixedInMemoryLruCache;
+use SMW\SQLStore\EntityStore\IdCacheManager;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\IdCacheManager
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class IdCacheManagerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $caches;
+
+ protected function setUp() {
+
+ $this->caches = [
+ 'entity.id' => new FixedInMemoryLruCache(),
+ 'entity.sort' => new FixedInMemoryLruCache(),
+ 'entity.lookup' => new FixedInMemoryLruCache(),
+ 'table.hash' => new FixedInMemoryLruCache()
+ ];
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ IdCacheManager::class,
+ new IdCacheManager( $this->caches )
+ );
+ }
+
+ public function testComputeSha1() {
+
+ $this->assertInternalType(
+ 'string',
+ IdCacheManager::computeSha1( [] )
+ );
+ }
+
+ public function testGet() {
+
+ $instance = new IdCacheManager( $this->caches );
+
+ $this->assertInstanceOf(
+ FixedInMemoryLruCache::class,
+ $instance->get( 'entity.sort' )
+ );
+ }
+
+ public function testGetThrowsException() {
+
+ $instance = new IdCacheManager( $this->caches );
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->get( 'foo' );
+ }
+
+ public function testSetCache() {
+
+ $instance = new IdCacheManager( $this->caches );
+
+ $instance->setCache( 'foo', 0, '', '', 42, 'bar' );
+
+ $this->assertEquals(
+ 42,
+ $instance->getId( [ 'foo', 0, '', '' ] )
+ );
+
+ $this->assertEquals(
+ false,
+ $instance->getId( [ 'foo', '0', '', '' ] )
+ );
+
+ $this->assertEquals(
+ 'bar',
+ $instance->getSort( [ 'foo', 0, '', '' ] )
+ );
+ }
+
+ public function testDeleteCache() {
+
+ $instance = new IdCacheManager( $this->caches );
+
+ $instance->setCache( 'foo', 0, '', '', '42', 'bar' );
+
+ $this->assertEquals(
+ 42,
+ $instance->getId( [ 'foo', 0, '', '' ] )
+ );
+
+ $instance->deleteCache( 'foo', 0, '', '' );
+
+ $this->assertEquals(
+ false,
+ $instance->getId( [ 'foo', '0', '', '' ] )
+ );
+
+ $this->assertEquals(
+ false,
+ $instance->getSort( [ 'foo', 0, '', '' ] )
+ );
+ }
+
+ public function testHasCache() {
+
+ $instance = new IdCacheManager( $this->caches );
+
+ $instance->setCache( 'foo', 0, '', '', '42', 'bar' );
+
+ $this->assertEquals(
+ false,
+ $instance->hasCache( [ 'foo', 0, '', '' ] )
+ );
+
+ $this->assertEquals(
+ true,
+ $instance->hasCache( $instance->computeSha1( [ 'foo', 0, '', '' ] ) )
+ );
+
+ }
+
+ public function testDeleteCacheById() {
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->once() )
+ ->method( 'delete' )
+ ->with( $this->equalTo( IdCacheManager::computeSha1( [ 'foo', 0, '', '' ] ) ) );
+
+ $this->caches['entity.id'] = $cache;
+
+ $instance = new IdCacheManager( $this->caches );
+ $instance->setCache( 'foo', 0, '', '', '42', 'bar' );
+
+ $instance->deleteCacheById( 42 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdChangerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdChangerTest.php
new file mode 100644
index 00000000..7a41f4ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdChangerTest.php
@@ -0,0 +1,202 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\SQLStore\EntityStore\IdChanger;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\IdChanger
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class IdChangerTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+ private $conection;
+
+ protected function setUp() {
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getConnection', 'getPropertyTables' ] )
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ IdChanger::class,
+ new IdChanger( $this->store )
+ );
+ }
+
+ public function testChange_IdSubject_Fields_NotFixedPropertyTable() {
+
+ $table = $this->getMockBuilder( 'SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $table->expects( $this->any() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $table->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $table->expects( $this->any() )
+ ->method( 'getFields' )
+ ->will( $this->returnValue( [ '_foo' => \SMW\SQLStore\TableBuilder\FieldType::FIELD_ID ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->onConsecutiveCalls( [ $table ] ) );
+
+ $this->connection->expects( $this->at( 0 ) )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 's_id' => 1001 ] ),
+ $this->equalTo( [ 's_id' => 42 ] ) );
+
+ $this->connection->expects( $this->at( 1 ) )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'p_id' => 1001 ] ),
+ $this->equalTo( [ 'p_id' => 42 ] ) );
+
+ $this->connection->expects( $this->at( 2 ) )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ '_foo' => 1001 ] ),
+ $this->equalTo( [ '_foo' => 42 ] ) );
+
+ $instance = new IdChanger(
+ $this->store
+ );
+
+ $instance->change( 42, 1001 );
+ }
+
+ public function testChange_IdSubject_PropertyNS_Fields_NotFixedPropertyTable() {
+
+ $table = $this->getMockBuilder( 'SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $table->expects( $this->any() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $table->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $table->expects( $this->any() )
+ ->method( 'getFields' )
+ ->will( $this->returnValue( [ '_foo' => \SMW\SQLStore\TableBuilder\FieldType::FIELD_ID ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->onConsecutiveCalls( [ $table ] ) );
+
+ $this->connection->expects( $this->at( 0 ) )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 's_id' => 1001 ] ),
+ $this->equalTo( [ 's_id' => 42 ] ) );
+
+ $this->connection->expects( $this->at( 1 ) )
+ ->method( 'delete' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'p_id' => 42 ] ) );
+
+ $this->connection->expects( $this->at( 2 ) )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ '_foo' => 1001 ] ),
+ $this->equalTo( [ '_foo' => 42 ] ) );
+
+ $instance = new IdChanger(
+ $this->store
+ );
+
+ $instance->change( 42, 1001, SMW_NS_PROPERTY, NS_MAIN );
+ }
+
+ public function testChange_IdSubject_ConceptNS_Fields_NotFixedPropertyTable() {
+
+ $table = $this->getMockBuilder( 'SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $table->expects( $this->any() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $table->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $table->expects( $this->any() )
+ ->method( 'getFields' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->onConsecutiveCalls( [ $table ] ) );
+
+ $this->connection->expects( $this->at( 0 ) )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 's_id' => 1001 ] ),
+ $this->equalTo( [ 's_id' => 42 ] ) );
+
+ $this->connection->expects( $this->at( 1 ) )
+ ->method( 'delete' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 's_id' => 42 ] ) );
+
+ $this->connection->expects( $this->at( 2 ) )
+ ->method( 'delete' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 's_id' => 42 ] ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'o_id' => 1001 ] ),
+ $this->equalTo( [ 'o_id' => 42 ] ) );
+
+ $instance = new IdChanger(
+ $this->store
+ );
+
+ $instance->change( 42, 1001, SMW_NS_CONCEPT, NS_MAIN );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdEntityFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdEntityFinderTest.php
new file mode 100644
index 00000000..02efa06c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/IdEntityFinderTest.php
@@ -0,0 +1,232 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIWikiPage;
+use SMW\IteratorFactory;
+use SMW\SQLStore\EntityStore\IdEntityFinder;
+use SMW\MediaWiki\Connection\Query;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\IdEntityFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class IdEntityFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $cache;
+ private $iteratorFactory;
+ private $idCacheManager;
+ private $store;
+ private $conection;
+
+ protected function setUp() {
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->idCacheManager = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\IdCacheManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->idCacheManager->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnValue( $this->cache ) );
+
+ $this->iteratorFactory = $this->getMockBuilder( '\SMW\IteratorFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMockForAbstractClass();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ IdEntityFinder::class,
+ new IdEntityFinder( $this->store, $this->iteratorFactory, $this->idCacheManager )
+ );
+ }
+
+ public function testGetDataItemForNonCachedId() {
+
+ $row = new \stdClass;
+ $row->smw_title = 'Foo';
+ $row->smw_namespace = 0;
+ $row->smw_iw = '';
+ $row->smw_subobject ='';
+ $row->smw_sortkey ='';
+ $row->smw_sort ='';
+ $row->smw_hash = 'x99w';
+
+ $this->cache->expects( $this->once() )
+ ->method( 'save' )
+ ->with(
+ $this->equalTo( 42 ),
+ $this->anything() );
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'select' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'smw_id' => 42 ] ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new IdEntityFinder(
+ $this->store,
+ $this->iteratorFactory,
+ $this->idCacheManager
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $instance->getDataItemById( 42 )
+ );
+ }
+
+ public function testGetDataItemForCachedId() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( new DIWikiPage( 'Foo', NS_MAIN ) ) );
+
+ $this->connection->expects( $this->never() )
+ ->method( 'selectRow' );
+
+ $instance = new IdEntityFinder(
+ $this->store,
+ $this->iteratorFactory,
+ $this->idCacheManager
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $instance->getDataItemById( 42 )
+ );
+ }
+
+ public function testPredefinedPropertyItem() {
+
+ $dataItem = new DIWikiPage( '_MDAT', SMW_NS_PROPERTY );
+ $dataItem->setId( 42 );
+ $dataItem->setSortKey( 'bar' );
+ $dataItem->setOption( 'sort', 'BAR' );
+
+ $row = new \stdClass;
+ $row->smw_title = '_MDAT';
+ $row->smw_namespace = SMW_NS_PROPERTY;
+ $row->smw_iw = '';
+ $row->smw_subobject = '';
+ $row->smw_sortkey = 'bar';
+ $row->smw_sort = 'BAR';
+ $row->smw_hash = 'x99w';
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'select' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'smw_id' => 42 ] ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new IdEntityFinder(
+ $this->store,
+ $this->iteratorFactory,
+ $this->idCacheManager
+ );
+
+ $this->assertEquals(
+ $dataItem,
+ $instance->getDataItemById( 42 )
+ );
+ }
+
+ public function testNullForUnknownId() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'select' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new IdEntityFinder(
+ $this->store,
+ $this->iteratorFactory,
+ $this->idCacheManager
+ );
+
+ $this->assertNull(
+ $instance->getDataItemById( 42 )
+ );
+ }
+
+ public function testGetDataItemsFromList() {
+
+ $expected = new DIWikiPage( 'Foo', 0, '', '' );
+ $expected->setId( 42 );
+ $expected->setSortKey( '...' );
+ $expected->setOption( 'sort', '...' );
+
+ $row = new \stdClass;
+ $row->smw_id = 42;
+ $row->smw_title = 'Foo';
+ $row->smw_namespace = 0;
+ $row->smw_iw = '';
+ $row->smw_subobject ='';
+ $row->smw_sortkey = '...';
+ $row->smw_sort = '...';
+ $row->smw_hash = 'x99w';
+
+ $this->connection->expects( $this->once() )
+ ->method( 'select' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'smw_id' => [ 42 ] ] ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new IdEntityFinder(
+ $this->store,
+ new IteratorFactory(),
+ $this->idCacheManager
+ );
+
+ foreach ( $instance->getDataItemsFromList( [ 42 ] ) as $value ) {
+ $this->assertEquals(
+ $expected,
+ $value
+ );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/NativeEntityLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/NativeEntityLookupTest.php
new file mode 100644
index 00000000..ab5dc99c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/NativeEntityLookupTest.php
@@ -0,0 +1,212 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SQLStore\EntityStore\NativeEntityLookup;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\NativeEntityLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class NativeEntityLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ NativeEntityLookup::class,
+ new NativeEntityLookup( $store )
+ );
+ }
+
+ public function testGetSemanticData() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $reader = $this->getMockBuilder( '\SMWSQLStore3Readers' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reader->expects( $this->once() )
+ ->method( 'getSemanticData' )
+ ->with(
+ $this->equalTo( $subject ),
+ $this->anything() );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getReader' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getReader' )
+ ->will( $this->returnValue( $reader ) );
+
+ $instance = new NativeEntityLookup(
+ $store
+ );
+
+ $instance->getSemanticData( $subject );
+ }
+
+ public function testGetProperties() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $reader = $this->getMockBuilder( '\SMWSQLStore3Readers' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reader->expects( $this->once() )
+ ->method( 'getProperties' )
+ ->with(
+ $this->equalTo( $subject ),
+ $this->anything() );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getReader' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getReader' )
+ ->will( $this->returnValue( $reader ) );
+
+ $instance = new NativeEntityLookup(
+ $store
+ );
+
+ $instance->getProperties( $subject );
+ }
+
+ public function testGetPropertyValues() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+ $property = new DIProperty( 'Bar' );
+
+ $reader = $this->getMockBuilder( '\SMWSQLStore3Readers' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reader->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->with(
+ $this->equalTo( $subject ),
+ $this->equalTo( $property ),
+ $this->anything() );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getReader' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getReader' )
+ ->will( $this->returnValue( $reader ) );
+
+ $instance = new NativeEntityLookup(
+ $store
+ );
+
+ $instance->getPropertyValues( $subject, $property );
+ }
+
+ public function testGetPropertySubjects() {
+
+ $property = new DIProperty( 'Bar' );
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $reader = $this->getMockBuilder( '\SMWSQLStore3Readers' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reader->expects( $this->once() )
+ ->method( 'getPropertySubjects' )
+ ->with(
+ $this->equalTo( $property ),
+ $this->equalTo( $subject ),
+ $this->anything() );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getReader' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getReader' )
+ ->will( $this->returnValue( $reader ) );
+
+ $instance = new NativeEntityLookup(
+ $store
+ );
+
+ $instance->getPropertySubjects( $property, $subject );
+ }
+
+ public function testGetAllPropertySubjects() {
+
+ $property = new DIProperty( 'Bar' );
+
+ $reader = $this->getMockBuilder( '\SMWSQLStore3Readers' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reader->expects( $this->once() )
+ ->method( 'getAllPropertySubjects' )
+ ->with( $this->equalTo( $property ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getReader' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getReader' )
+ ->will( $this->returnValue( $reader ) );
+
+ $instance = new NativeEntityLookup(
+ $store
+ );
+
+ $instance->getAllPropertySubjects( $property );
+ }
+
+ public function testGetInProperties() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $reader = $this->getMockBuilder( '\SMWSQLStore3Readers' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $reader->expects( $this->once() )
+ ->method( 'getInProperties' )
+ ->with( $this->equalTo( $subject ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getReader' ] )
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getReader' )
+ ->will( $this->returnValue( $reader ) );
+
+ $instance = new NativeEntityLookup(
+ $store
+ );
+
+ $instance->getInProperties( $subject );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertiesLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertiesLookupTest.php
new file mode 100644
index 00000000..0bc96fc4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertiesLookupTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIWikiPage;
+use SMW\Options;
+use SMW\SQLStore\EntityStore\PropertiesLookup;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\PropertiesLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PropertiesLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ PropertiesLookup::class,
+ new PropertiesLookup( $store )
+ );
+ }
+
+ public function testLookupForNonFixedPropertyTable() {
+
+ $dataItem = DIWikiPage::newFromText( __METHOD__ );
+ $dataItem->setId( 42 );
+
+ $resultWrapper = $this->getMockBuilder( '\FakeResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef->expects( $this->atLeastOnce() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $query = $this->getMockBuilder( '\SMW\MediaWiki\Connection\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'execute' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getSQLOptions', 'getSQLConditions' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSQLOptions' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSQLConditions' )
+ ->will( $this->returnValue( '' ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new PropertiesLookup(
+ $store
+ );
+
+ $instance->fetchFromTable( $dataItem, $propertyTableDef );
+ }
+
+ public function testLookupForFixedPropertyTable() {
+
+ $dataItem = DIWikiPage::newFromText( __METHOD__ );
+ $dataItem->setId( 1001 );
+
+ $resultWrapper = $this->getMockBuilder( '\FakeResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef->expects( $this->atLeastOnce() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $query = $this->getMockBuilder( '\SMW\MediaWiki\Connection\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'execute' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new PropertiesLookup(
+ $store
+ );
+
+ $instance->fetchFromTable( $dataItem, $propertyTableDef );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertySubjectsLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertySubjectsLookupTest.php
new file mode 100644
index 00000000..014a246d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/PropertySubjectsLookupTest.php
@@ -0,0 +1,156 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIWikiPage;
+use SMW\Options;
+use SMW\SQLStore\EntityStore\PropertySubjectsLookup;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\PropertySubjectsLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PropertySubjectsLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ PropertySubjectsLookup::class,
+ new PropertySubjectsLookup( $store )
+ );
+ }
+
+ public function testLookupForNonFixedPropertyTable() {
+
+ $dataItem = DIWikiPage::newFromText( __METHOD__ );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->atLeastOnce() )
+ ->method( 'getWhereConds' )
+ ->will( $this->returnValue( [ 'o_id' => 42 ] ) );
+
+ $propertyTableDef = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef->expects( $this->atLeastOnce() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $query = $this->getMockBuilder( '\SMW\MediaWiki\Connection\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getDataItemHandlerForDIType', 'getSQLOptions', 'getSQLConditions' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSQLOptions' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSQLConditions' )
+ ->will( $this->returnValue( '' ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $instance = new PropertySubjectsLookup(
+ $store
+ );
+
+ $instance->fetchFromTable( 42, $propertyTableDef, $dataItem );
+ }
+
+ public function testLookupForFixedPropertyTable() {
+
+ $dataItem = DIWikiPage::newFromText( __METHOD__ );
+
+ $resultWrapper = $this->getMockBuilder( '\FakeResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->atLeastOnce() )
+ ->method( 'getWhereConds' )
+ ->will( $this->returnValue( [ 'o_id' => 42 ] ) );
+
+ $propertyTableDef = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef->expects( $this->atLeastOnce() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $query = $this->getMockBuilder( '\SMW\MediaWiki\Connection\Query' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getDataItemHandlerForDIType' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $instance = new PropertySubjectsLookup(
+ $store
+ );
+
+ $instance->fetchFromTable( 42, $propertyTableDef, $dataItem );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SemanticDataLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SemanticDataLookupTest.php
new file mode 100644
index 00000000..de5e5872
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SemanticDataLookupTest.php
@@ -0,0 +1,356 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMWDIBlob as DIBlob;
+use SMW\RequestOptions;
+use SMW\SQLStore\EntityStore\SemanticDataLookup;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\SemanticDataLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SemanticDataLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $connection;
+ private $dataItemHandler;
+ private $query;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'findPropertyTableID', 'getDataItemHandlerForDIType', 'getObjectIds' ] )
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $this->dataItemHandler ) );
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableName' )
+ ->will( $this->returnArgument(0) );
+
+ $this->query = new \SMW\MediaWiki\Connection\Query( $this->connection );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $this->query ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $this->store->setConnectionManager( $connectionManager );
+ }
+
+ public function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SemanticDataLookup::class,
+ new SemanticDataLookup( $this->store )
+ );
+ }
+
+ public function testNewStubSemanticData_FromDIWikiPage() {
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\StubSemanticData',
+ $instance->newStubSemanticData( DIWikiPage::newFromText( __METHOD__ ) )
+ );
+ }
+
+ public function testNewStubSemanticData_FromSemanticData() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\StubSemanticData',
+ $instance->newStubSemanticData( $semanticData )
+ );
+ }
+
+ public function testNewStubSemanticDataThrowsException() {
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->newStubSemanticData( 'Foo' );
+ }
+
+ public function testGetTableUsageInfo() {
+
+ $property = new DIProperty( 'Foo' );
+
+ $this->store->expects( $this->once() )
+ ->method( 'findPropertyTableID' )
+ ->with( $this->equalTo( $property ) )
+ ->will( $this->returnValue( '__bar__' ) );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [ $property ] ) );
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $this->assertEquals(
+ [ '__bar__' => true ],
+ $instance->getTableUsageInfo( $semanticData )
+ );
+ }
+
+ public function testSemanticDataFromTable() {
+
+ $row = new \stdClass;
+ $row->prop = 'FOO';
+ $row->v0 = '1001';
+
+ $this->dataItemHandler->expects( $this->any() )
+ ->method( 'getFetchFields' )
+ ->will( $this->returnValue( [ 'fooField' => 'fieldType' ] ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $semanticData = $instance->fetchSemanticData(
+ 42,
+ $subject,
+ $propertyTable
+ );
+ }
+
+ public function testSemanticDataFromTable_WithConstraint() {
+
+ $row = new \stdClass;
+ $row->prop = 'FOO';
+ $row->v0 = '1001';
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 9999 ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->dataItemHandler->expects( $this->any() )
+ ->method( 'getFetchFields' )
+ ->will( $this->returnValue( [ 'fooField' => 'fieldType' ] ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnCallback( function( $value ) { return "'$value'"; } ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $requestOptions = new RequestOptions();
+ $requestOptions->conditionConstraint = true;
+ $requestOptions->setLimit( 4 );
+
+ $requestOptions = $instance->newRequestOptions(
+ $propertyTable,
+ $property,
+ $requestOptions
+ );
+
+ $instance->fetchSemanticData( 42, $subject, $propertyTable, $requestOptions );
+
+ $this->assertEquals(
+ "SELECT p.smw_title AS prop, fooField AS v0 FROM " .
+ "INNER JOIN smw_object_ids AS p ON p_id=p.smw_id " .
+ "WHERE (s_id='42') AND (p.smw_iw!=':smw') AND (p.smw_iw!=':smw-delete') AND (p_id='9999') " .
+ "LIMIT 4",
+ $this->query->build()
+ );
+ }
+
+ public function testSemanticData_NoDataItem() {
+
+ $row = new \stdClass;
+ $row->prop = 'FOO';
+ $row->v0 = '1001';
+
+ $this->dataItemHandler->expects( $this->any() )
+ ->method( 'getFetchFields' )
+ ->will( $this->returnValue( [ 'fooField' => 'fieldType' ] ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnCallback( function( $value ) { return "'$value'"; } ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $instance->fetchSemanticData( 42, null, $propertyTable );
+
+ $this->assertEquals(
+ "SELECT p.smw_title AS prop, fooField AS v0 FROM " .
+ "INNER JOIN smw_object_ids AS p ON p_id=p.smw_id " .
+ "WHERE (s_id='42') AND (p.smw_iw!=':smw') AND (p.smw_iw!=':smw-delete')",
+ $this->query->build()
+ );
+ }
+
+ public function testFetchSemanticData_NonWikiPageTable_DISTINCT_SELECT() {
+
+ $row = new \stdClass;
+ $row->prop = 'FOO';
+ $row->v0 = '1001';
+
+ $this->dataItemHandler->expects( $this->any() )
+ ->method( 'getFetchFields' )
+ ->will( $this->returnValue( [ 'fooField' => 'fieldType' ] ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $propertyTable->expects( $this->atLeastOnce() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( 'bar_table' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnCallback( function( $value ) { return "'$value'"; } ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $dataItem = new DIBlob( __METHOD__ );
+
+ $requestOptions = new RequestOptions();
+ $requestOptions->setLimit( 4 );
+
+ $instance = new SemanticDataLookup(
+ $this->store
+ );
+
+ $instance->fetchSemanticData( 42, $dataItem, $propertyTable, $requestOptions );
+
+ $this->assertEquals(
+ "SELECT DISTINCT fooField AS v0 FROM bar_table WHERE (p_id='42') LIMIT 4",
+ $this->query->build()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/StubSemanticDataTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/StubSemanticDataTest.php
new file mode 100644
index 00000000..465a048d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/StubSemanticDataTest.php
@@ -0,0 +1,162 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SQLStore\EntityStore\StubSemanticData;
+use SMW\Tests\TestEnvironment;
+use SMWDITime as DITime;
+
+/**
+ * @covers SMW\SQLStore\EntityStore\StubSemanticData
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class StubSemanticDataTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $testEnvironment;
+
+ protected function setUp() {
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $this->assertInstanceOf(
+ StubSemanticData::class,
+ StubSemanticData::newFromSemanticData( $semanticData, $this->store )
+ );
+ }
+
+ public function testNotToResolveSubobjectsForRedirect() {
+
+ $instance = $this->getMockBuilder( StubSemanticData::class )
+ ->setConstructorArgs( [
+ DIWikiPage::newFromText( __METHOD__ ),
+ $this->store ] )
+ ->setMethods( [
+ 'getProperties',
+ 'isRedirect',
+ 'getPropertyValues' ] )
+ ->getMock();
+
+ $instance->expects( $this->once() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [ new DIProperty( '_SOBJ' ) ] ) );
+
+ $instance->expects( $this->once() )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( true ) );
+
+ $instance->expects( $this->never() )
+ ->method( 'getPropertyValues' );
+
+ $instance->getSubSemanticData();
+ }
+
+ public function testGetPropertyValues() {
+
+ $instance = StubSemanticData::newFromSemanticData(
+ new SemanticData( DIWikiPage::newFromText( __METHOD__ ) ),
+ $this->store
+ );
+
+ $this->assertInstanceOf(
+ 'SMW\DIWikiPage',
+ $instance->getSubject()
+ );
+
+ $this->assertEmpty(
+ $instance->getPropertyValues( new DIProperty( 'unknownInverseProperty', true ) )
+ );
+
+ $this->assertEmpty(
+ $instance->getPropertyValues( new DIProperty( 'unknownProperty' ) )
+ );
+ }
+
+ /**
+ * @dataProvider propertyObjectProvider
+ */
+ public function testPhpSerialization( $property, $dataItem ) {
+
+ $instance = StubSemanticData::newFromSemanticData(
+ new SemanticData( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ $this->store
+ );
+
+ $instance->addPropertyObjectValue(
+ $property,
+ $dataItem
+ );
+
+ $serialization = serialize( $instance );
+
+ $this->assertEquals(
+ $instance->getHash(),
+ unserialize( $serialization )->getHash()
+ );
+ }
+
+ /**
+ * @dataProvider propertyObjectProvider
+ */
+ public function testRemovePropertyObjectValue( $property, $dataItem ) {
+
+ $instance = StubSemanticData::newFromSemanticData(
+ new SemanticData( new DIWikiPage( 'Foo', NS_MAIN ) ),
+ $this->store
+ );
+
+ $instance->addPropertyObjectValue( $property, $dataItem );
+ $this->assertFalse( $instance->isEmpty() );
+
+ $instance->removePropertyObjectValue( $property, $dataItem );
+ $this->assertTrue( $instance->isEmpty() );
+ }
+
+ public function propertyObjectProvider() {
+
+ $provider = [];
+
+ // #0
+ $provider[] = [
+ new DIProperty( '_MDAT' ),
+ DITime::newFromTimestamp( 1272508903 )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SubobjectListFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SubobjectListFinderTest.php
new file mode 100644
index 00000000..a7136826
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/SubobjectListFinderTest.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\ApplicationFactory;
+use SMW\DIWikiPage;
+use SMW\SQLStore\EntityStore\SubobjectListFinder;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\SubobjectListFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SubobjectListFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $iteratorFactory;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->iteratorFactory = ApplicationFactory::getInstance()->getIteratorFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $iteratorFactory = $this->getMockBuilder( '\SMW\IteratorFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ SubobjectListFinder::class,
+ new SubobjectListFinder( $store, $iteratorFactory )
+ );
+ }
+
+ /**
+ * @dataProvider subjectProvider
+ */
+ public function testNewMappingIterator( $subject ) {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SubobjectListFinder(
+ $store,
+ $this->iteratorFactory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\MappingIterator',
+ $instance->find( $subject )
+ );
+ }
+
+ /**
+ * @dataProvider subjectProvider
+ */
+ public function testIterateOn( $subject ) {
+
+ $row = new \stdClass;
+ $row->smw_id = 42;
+ $row->smw_sortkey = 'sort';
+ $row->smw_sort = 'SORT';
+ $row->smw_subobject = '10000000001';
+
+ $expected = [
+ 'Foo', 0, '', 'sort', '10000000001'
+ ];
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( 'smw_title= AND smw_namespace= AND smw_iw= AND smw_subobject!=' ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getDataItemHandlerForDIType' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SubobjectListFinder(
+ $store,
+ $this->iteratorFactory
+ );
+
+ foreach ( $instance->find( $subject ) as $v ) {
+ $this->assertEquals( 42, $v->getId() );
+ }
+ }
+
+ public function subjectProvider() {
+
+ $provider[] = [
+ DIWikiPage::newFromText( 'Foo' )
+ ];
+
+ $provider[] = [
+ DIWikiPage::newFromText( 'Bar', SMW_NS_PROPERTY )
+ ];
+
+ $provider[] = [
+ DIWikiPage::newFromText( 'Modification date', SMW_NS_PROPERTY )
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/TraversalPropertyLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/TraversalPropertyLookupTest.php
new file mode 100644
index 00000000..50ca8b28
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/TraversalPropertyLookupTest.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\DIWikiPage;
+use SMW\Options;
+use SMW\SQLStore\EntityStore\TraversalPropertyLookup;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\TraversalPropertyLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TraversalPropertyLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ TraversalPropertyLookup::class,
+ new TraversalPropertyLookup( $store )
+ );
+ }
+
+ public function testlookupForNonFixedPropertyTable() {
+
+ $dataItem = DIWikiPage::newFromText( __METHOD__ );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->atLeastOnce() )
+ ->method( 'getWhereConds' )
+ ->will( $this->returnValue( [ 'o_id' => 42 ] ) );
+
+ $propertyTableDef = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef->expects( $this->atLeastOnce() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getDataItemHandlerForDIType', 'getSQLOptions', 'getSQLConditions' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSQLOptions' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSQLConditions' )
+ ->will( $this->returnValue( '' ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $instance = new TraversalPropertyLookup(
+ $store
+ );
+
+ $instance->fetchFromTable( $propertyTableDef, $dataItem );
+ }
+
+ public function testlookupForFixedPropertyTable() {
+
+ $dataItem = DIWikiPage::newFromText( __METHOD__ );
+
+ $resultWrapper = $this->getMockBuilder( '\FakeResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->atLeastOnce() )
+ ->method( 'getWhereConds' )
+ ->will( $this->returnValue( [ 'o_id' => 42 ] ) );
+
+ $propertyTableDef = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDef->expects( $this->atLeastOnce() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getDataItemHandlerForDIType' ] )
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $instance = new TraversalPropertyLookup(
+ $store
+ );
+
+ $instance->fetchFromTable( $propertyTableDef, $dataItem );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/UniquenessLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/UniquenessLookupTest.php
new file mode 100644
index 00000000..197975e1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityStore/UniquenessLookupTest.php
@@ -0,0 +1,134 @@
+<?php
+
+namespace SMW\Tests\SQLStore\EntityStore;
+
+use SMW\SQLStore\EntityStore\UniquenessLookup;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Connection\Query;
+use SMW\IteratorFactory;
+
+/**
+ * @covers \SMW\SQLStore\EntityStore\UniquenessLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class UniquenessLookupTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $connection;
+ private $iteratorFactory;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $this->iteratorFactory = $this->getMockBuilder( '\SMW\IteratorFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ UniquenessLookup::class,
+ new UniquenessLookup( $this->store, $this->iteratorFactory )
+ );
+ }
+
+ public function testIsUnique() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'tableName' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $query = new \SMW\MediaWiki\Connection\Query( $connection );
+
+ $resultWrapper = $this->getMockBuilder( '\ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $instance = new UniquenessLookup(
+ $this->store,
+ $this->iteratorFactory
+ );
+
+ $instance->isUnique( DIWikiPage::newFromText( 'Foo' ) );
+
+ $this->assertJsonStringEqualsJsonString(
+ '{' .
+ '"tables": "smw_object_ids",' .
+ '"fields":["smw_id","smw_sortkey"],' .
+ '"conditions":[["smw_title=Foo"],["smw_namespace=0"],["smw_subobject="],["smw_iw!=:smw"],["smw_iw!=:smw-delete"],["smw_iw!=:smw-redi"]],' .
+ '"joins":[],' .
+ '"options":{"LIMIT":2},"alias":"","index":0,"autocommit":false}',
+ (string)$query
+ );
+ }
+
+ public function testFindDuplicates() {
+
+ $row = new \stdClass;
+ $row->count = 42;
+ $row->smw_title = 'Foo';
+ $row->smw_namespace = 0;
+ $row->smw_iw = '';
+ $row->smw_subobject ='';
+
+ $query = new Query( $this->connection );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new UniquenessLookup(
+ $this->store,
+ new IteratorFactory()
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\MappingIterator',
+ $instance->findDuplicates()
+ );
+
+ $this->assertContains(
+ 'HAVING":"count(*) > 1',
+ $query->__toString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityValueUniquenessConstraintCheckerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityValueUniquenessConstraintCheckerTest.php
new file mode 100644
index 00000000..6cd6f7f4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/EntityValueUniquenessConstraintCheckerTest.php
@@ -0,0 +1,165 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\EntityValueUniquenessConstraintChecker;
+use SMW\DIWikiPage;
+
+/**
+ * @covers \SMW\SQLStore\EntityValueUniquenessConstraintChecker
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class EntityValueUniquenessConstraintCheckerTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $connection;
+ private $iteratorFactory;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $this->iteratorFactory = $this->getMockBuilder( '\SMW\IteratorFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ EntityValueUniquenessConstraintChecker::class,
+ new EntityValueUniquenessConstraintChecker( $this->store, $this->iteratorFactory )
+ );
+ }
+
+ public function testCheckConstraint() {
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher->expects( $this->any() )
+ ->method( 'findTableIdForProperty' )
+ ->will( $this->returnValue( '_foo' ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getConnection', 'getPropertyTables', 'getPropertyTableInfoFetcher' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->any() )
+ ->method( 'getFixedProperty' )
+ ->will( $this->returnValue( '_UNKNOWN_FIXED_PROPERTY' ) );
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'getDiType' )
+ ->will( $this->returnValue( \SMWDataItem::TYPE_BLOB ) );
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( 'smw_foo' ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ '_foo' => $propertyTable ] ) );
+
+ $requestOptions = $this->getMockBuilder( '\SMW\RequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $requestOptions->expects( $this->any() )
+ ->method( 'getExtraConditions' )
+ ->will( $this->returnValue( [] ) );
+
+ $requestOptions->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 42 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'tableName' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $query = new \SMW\MediaWiki\Connection\Query( $connection );
+
+ $resultWrapper = $this->getMockBuilder( '\ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $instance = new EntityValueUniquenessConstraintChecker(
+ $store,
+ $this->iteratorFactory
+ );
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataItem = $this->getMockBuilder( '\SMWDIBlob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance->checkConstraint( $property, $dataItem, $requestOptions );
+
+ $this->assertJsonStringEqualsJsonString(
+ '{' .
+ '"tables": "smw_foo AS t1",' .
+ '"fields":[["t1.s_id"]],' .
+ '"conditions":[{"AND":["t1.o_hash="]}],' .
+ '"joins":[],' .
+ '"options":{"LIMIT":42},"alias":"t","index":1,"autocommit":false}',
+ (string)$query
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/PropertyStatisticsInvalidArgumentExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/PropertyStatisticsInvalidArgumentExceptionTest.php
new file mode 100644
index 00000000..41de869d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/PropertyStatisticsInvalidArgumentExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Exception;
+
+use SMW\SQLStore\Exception\PropertyStatisticsInvalidArgumentException;
+
+/**
+ * @covers \SMW\SQLStore\Exception\PropertyStatisticsInvalidArgumentException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyStatisticsInvalidArgumentExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new PropertyStatisticsInvalidArgumentException();
+
+ $this->assertInstanceof(
+ '\SMW\SQLStore\Exception\PropertyStatisticsInvalidArgumentException',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\InvalidArgumentException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/TableMissingIdFieldExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/TableMissingIdFieldExceptionTest.php
new file mode 100644
index 00000000..07980f1c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Exception/TableMissingIdFieldExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Exception;
+
+use SMW\SQLStore\Exception\TableMissingIdFieldException;
+
+/**
+ * @covers \SMW\SQLStore\Exception\TableMissingIdFieldException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TableMissingIdFieldExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new TableMissingIdFieldException( 'foo' );
+
+ $this->assertInstanceof(
+ TableMissingIdFieldException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/InstallerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/InstallerTest.php
new file mode 100644
index 00000000..084e4fcb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/InstallerTest.php
@@ -0,0 +1,348 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use Onoi\MessageReporter\MessageReporterFactory;
+use SMW\SQLStore\Installer;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\Installer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class InstallerTest extends \PHPUnit_Framework_TestCase {
+
+ private $spyMessageReporter;
+ private $testEnvironment;
+ private $tableSchemaManager;
+ private $tableBuilder;
+ private $tableIntegrityExaminer;
+ private $file;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyMessageReporter = MessageReporterFactory::getInstance()->newSpyMessageReporter();
+
+ $this->tableSchemaManager = $this->getMockBuilder( '\SMW\SQLStore\TableSchemaManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->tableIntegrityExaminer = $this->getMockBuilder( '\SMW\SQLStore\TableIntegrityExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->file = $this->getMockBuilder( '\SMW\Utils\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $this->jobQueue );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Installer::class,
+ new Installer( $this->tableSchemaManager, $this->tableBuilder, $this->tableIntegrityExaminer )
+ );
+ }
+
+ public function testInstall() {
+
+ $table = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\Table' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->tableSchemaManager->expects( $this->atLeastOnce() )
+ ->method( 'getTables' )
+ ->will( $this->returnValue( [ $table ] ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'create' ] )
+ ->getMockForAbstractClass();
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'create' );
+
+ $this->tableIntegrityExaminer->expects( $this->once() )
+ ->method( 'checkOnPostCreation' );
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->setFile( $this->file );
+
+ $instance->setOptions(
+ [
+ Installer::OPT_SCHEMA_UPDATE => false
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->install()
+ );
+ }
+
+ public function testInstallWithSupplementJobs() {
+
+ $this->jobQueue->expects( $this->exactly( 2 ) )
+ ->method( 'push' );
+
+ $table = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\Table' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->tableSchemaManager->expects( $this->atLeastOnce() )
+ ->method( 'getTables' )
+ ->will( $this->returnValue( [ $table ] ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'create' ] )
+ ->getMockForAbstractClass();
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'create' );
+
+ $this->tableIntegrityExaminer->expects( $this->once() )
+ ->method( 'checkOnPostCreation' );
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->setFile( $this->file );
+
+ $instance->setOptions(
+ [
+ Installer::OPT_SUPPLEMENT_JOBS => true
+ ]
+ );
+
+ $instance->install();
+ }
+
+ public function testInstallNonVerbose() {
+
+ $table = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\Table' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->tableSchemaManager->expects( $this->atLeastOnce() )
+ ->method( 'getTables' )
+ ->will( $this->returnValue( [ $table ] ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'create' ] )
+ ->getMockForAbstractClass();
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->setFile( $this->file );
+
+ $this->assertTrue(
+ $instance->install( false )
+ );
+ }
+
+ public function testUninstall() {
+
+ $table = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\Table' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->tableSchemaManager->expects( $this->once() )
+ ->method( 'getTables' )
+ ->will( $this->returnValue( [ $table ] ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'drop' ] )
+ ->getMockForAbstractClass();
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'drop' );
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+
+ $this->assertTrue(
+ $instance->uninstall()
+ );
+ }
+
+ public function testReportMessage() {
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $this->tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $callback = function() use( $instance ) {
+ $instance->reportMessage( 'Foo' );
+ };
+
+ $this->assertEquals(
+ 'Foo',
+ $this->testEnvironment->outputFromCallbackExec( $callback )
+ );
+ }
+
+ public function testIsGoodSchema() {
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $this->tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->isGoodSchema()
+ );
+ }
+
+ public function testMakeUpgradeKey() {
+
+ $var1 = [
+ 'smwgUpgradeKey' => '',
+ 'smwgFixedProperties' => [ 'Foo', 'Bar' ],
+ 'smwgPageSpecialProperties' => [ 'Foo', 'Bar' ]
+ ];
+
+ $var2 = [
+ 'smwgUpgradeKey' => '',
+ 'smwgFixedProperties' => [ 'Bar', 'Foo' ],
+ 'smwgPageSpecialProperties' => [ 'Bar', 'Foo' ]
+ ];
+
+ $this->assertEquals(
+ Installer::makeUpgradeKey( $var1 ),
+ Installer::makeUpgradeKey( $var2 )
+ );
+ }
+
+ public function testMakeUpgradeKey_SpecialFixedProperties() {
+
+ $var1 = [
+ 'smwgUpgradeKey' => '',
+ 'smwgFixedProperties' => [ 'Foo', 'Bar' ],
+ 'smwgPageSpecialProperties' => [ 'Foo', 'Bar' ]
+ ];
+
+ $var2 = [
+ 'smwgUpgradeKey' => '',
+ 'smwgFixedProperties' => [ 'Bar', 'Foo' ],
+ 'smwgPageSpecialProperties' => [ 'Bar', '_MDAT' ]
+ ];
+
+ $this->assertNotEquals(
+ Installer::makeUpgradeKey( $var1 ),
+ Installer::makeUpgradeKey( $var2 )
+ );
+ }
+
+ public function testSetUpgradeKey() {
+
+ $file = $this->getMockBuilder( '\SMW\Utils\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $file->expects( $this->once() )
+ ->method( 'write' );
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $this->tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $vars = [
+ 'smwgConfigFileDir' => 'Foo/',
+ 'smwgIP' => '',
+ 'smwgUpgradeKey' => '',
+ 'smwgFixedProperties' => [],
+ 'smwgPageSpecialProperties' => []
+ ];
+
+ $instance->setUpgradeKey( $vars, $this->spyMessageReporter, $file );
+ }
+
+ public function testSetUpgradeFile() {
+
+ $expected = json_encode( [ \SMW\Site::id() => [ 'Foo' => 42 ] ], JSON_PRETTY_PRINT );
+
+ $file = $this->getMockBuilder( '\SMW\Utils\File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $file->expects( $this->once() )
+ ->method( 'write' )
+ ->with(
+ $this->equalTo( 'Foo_dir/.smw.json' ),
+ $this->equalTo( $expected ) );
+
+ $instance = new Installer(
+ $this->tableSchemaManager,
+ $this->tableBuilder,
+ $this->tableIntegrityExaminer
+ );
+
+ $vars = [
+ 'smwgConfigFileDir' => 'Foo_dir'
+ ];
+
+ $instance->setUpgradeFile( $vars, [ 'Foo' => 42 ], $file );
+ }
+
+ public function testIncompleteTasks() {
+
+ $vars = [
+ 'smw.json' => [ \SMW\Site::id() => [ Installer::POPULATE_HASH_FIELD_COMPLETE => false ] ]
+ ];
+
+ $this->assertEquals(
+ [ 'smw-install-incomplete-populate-hash-field' ],
+ Installer::incompleteTasks( $vars )
+ );
+
+ $this->assertEquals(
+ [],
+ Installer::incompleteTasks( [] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/CachedListLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/CachedListLookupTest.php
new file mode 100644
index 00000000..139568f9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/CachedListLookupTest.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\SQLStore\Lookup\CachedListLookup;
+
+/**
+ * @covers \SMW\SQLStore\Lookup\CachedListLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class CachedListLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $listLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\ListLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\CachedListLookup',
+ new CachedListLookup( $listLookup, $cache, new \stdClass )
+ );
+ }
+
+ public function testfetchListFromCache() {
+
+ $expectedCachedItem = [
+ 'time' => 42,
+ 'list' => [ 'Foo' ]
+ ];
+
+ $listLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\ListLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $listLookup->expects( $this->atLeastOnce() )
+ ->method( 'getHash' )
+ ->will( $this->returnValue( 'Bar#123' ) );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->with( $this->stringContains( 'cacheprefix-foobar:smw:store:lookup:' ) )
+ ->will( $this->returnValue( true ) );
+
+ $cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( serialize( $expectedCachedItem ) ) );
+
+ $cacheOptions = new \stdClass;
+ $cacheOptions->useCache = true;
+
+ $instance = new CachedListLookup( $listLookup, $cache, $cacheOptions );
+ $instance->setCachePrefix( 'cacheprefix-foobar' );
+
+ $this->assertEquals(
+ [ 'Foo' ],
+ $instance->fetchList()
+ );
+
+ $this->assertEquals(
+ 42,
+ $instance->getTimestamp()
+ );
+
+ $this->assertEquals(
+ 'Bar#123',
+ $instance->getHash()
+ );
+
+ $this->assertTrue(
+ $instance->isFromCache()
+ );
+ }
+
+ public function testRetrieveResultListFromInjectedListLookup() {
+
+ $expectedCacheItem = [
+ 'time' => 42,
+ 'list' => [ 'Foo' ]
+ ];
+
+ $listLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\ListLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $listLookup->expects( $this->once() )
+ ->method( 'fetchList' )
+ ->will( $this->returnValue( [ 'Foo' ] ) );
+
+ $listLookup->expects( $this->once() )
+ ->method( 'getTimestamp' )
+ ->will( $this->returnValue( 42 ) );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->at( 1 ) )
+ ->method( 'save' )
+ ->with(
+ $this->stringContains( 'smw:store:lookup' ),
+ $this->anything( serialize( $expectedCacheItem ) ),
+ $this->equalTo( 1001 ) );
+
+ $cacheOptions = new \stdClass;
+ $cacheOptions->useCache = false;
+ $cacheOptions->ttl = 1001;
+
+ $instance = new CachedListLookup( $listLookup, $cache, $cacheOptions );
+
+ $this->assertEquals(
+ [ 'Foo' ],
+ $instance->fetchList()
+ );
+
+ $this->assertEquals(
+ 42,
+ $instance->getTimestamp()
+ );
+
+ $this->assertFalse(
+ $instance->isFromCache()
+ );
+ }
+
+ public function testDeleteCache() {
+
+ $listLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\ListLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $listLookup->expects( $this->once() )
+ ->method( 'getHash' )
+ ->will( $this->returnValue( 'Foo#123' ) );
+
+ $cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $cache->expects( $this->once() )
+ ->method( 'fetch' )
+ ->will( $this->returnValue( serialize( [ 'smw:store:lookup:6283479db90b04ad3a6db333a3c89766' => true ] ) ) );
+
+ $cache->expects( $this->atLeastOnce() )
+ ->method( 'delete' )
+ ->with(
+ $this->stringContains( 'smw:store:lookup' ) );
+
+ $cacheOptions = new \stdClass;
+
+ $instance = new CachedListLookup( $listLookup, $cache, $cacheOptions );
+ $instance->deleteCache();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyLabelSimilarityLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyLabelSimilarityLookupTest.php
new file mode 100644
index 00000000..ff781d44
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyLabelSimilarityLookupTest.php
@@ -0,0 +1,147 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\DataItemFactory;
+use SMW\RequestOptions;
+use SMW\SQLStore\Lookup\PropertyLabelSimilarityLookup;
+
+/**
+ * @covers \SMW\SQLStore\Lookup\PropertyLabelSimilarityLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PropertyLabelSimilarityLookupTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $propertyStatisticsStore;
+ private $requestOptions;
+ private $dataItemFactory;
+
+ protected function setUp() {
+
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestOptions = $this->getMockBuilder( '\SMW\RequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\PropertyLabelSimilarityLookup',
+ new PropertyLabelSimilarityLookup( $this->store )
+ );
+ }
+
+ public function testGetPropertyMaxCount() {
+
+ $this->store->expects( $this->any() )
+ ->method( 'getStatistics' )
+ ->will( $this->returnValue( [ 'TOTALPROPS' => 42 ] ) );
+
+ $propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyLabelSimilarityLookup(
+ $this->store,
+ $propertySpecificationLookup
+ );
+
+ $this->assertEquals(
+ 42,
+ $instance->getPropertyMaxCount()
+ );
+ }
+
+ public function testCompareAndFindLabels() {
+
+ $row = new \stdClass;
+ $row->smw_title = 'Foo';
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyLabelSimilarityLookup(
+ $this->store,
+ $propertySpecificationLookup
+ );
+
+ $requestOptions = new RequestOptions();
+
+ $instance->compareAndFindLabels( $requestOptions );
+
+ $this->assertEquals(
+ 1,
+ $instance->getLookupCount()
+ );
+ }
+
+ public function testCompareAndFindLabelsWithExemption() {
+
+ $row1 = new \stdClass;
+ $row1->smw_title = 'Foo';
+
+ $row2 = new \stdClass;
+ $row2->smw_title = 'Foobar';
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row1, $row2 ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertySpecificationLookup->expects( $this->any() )
+ ->method( 'getSpecification' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIWikiPage( 'Foobar', SMW_NS_PROPERTY ) ] ) );
+
+ $instance = new PropertyLabelSimilarityLookup(
+ $this->store,
+ $propertySpecificationLookup
+ );
+
+ $requestOptions = new RequestOptions();
+
+ $instance->setExemptionProperty( 'Bar' );
+ $instance->setThreshold( 10 );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->compareAndFindLabels( $requestOptions )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyUsageListLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyUsageListLookupTest.php
new file mode 100644
index 00000000..fd6a1f04
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/PropertyUsageListLookupTest.php
@@ -0,0 +1,216 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\DIProperty;
+use SMW\RequestOptions;
+use SMW\SQLStore\Lookup\PropertyUsageListLookup;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\Lookup\PropertyUsageListLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class PropertyUsageListLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $propertyStatisticsStore;
+ private $requestOptions;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestOptions = $this->getMockBuilder( '\SMWRequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\PropertyUsageListLookup',
+ new PropertyUsageListLookup( $this->store, $this->propertyStatisticsStore, $this->requestOptions )
+ );
+ }
+
+ public function testListLookupInterfaceMethodAccess() {
+
+ $instance = new PropertyUsageListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $this->requestOptions
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getTimestamp()
+ );
+
+ $this->assertFalse(
+ $instance->isFromCache()
+ );
+
+ $this->assertContains(
+ 'PropertyUsageListLookup',
+ $instance->getHash()
+ );
+ }
+
+ public function testLookupIdentifierChangedByRequestOptions() {
+
+ $requestOptions = new RequestOptions();
+
+ $instance = new PropertyUsageListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $requestOptions
+ );
+
+ $lookupIdentifier = $instance->getHash();
+
+ $requestOptions->limit = 100;
+
+ $instance = new PropertyUsageListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $requestOptions
+ );
+
+ $this->assertNotSame(
+ $lookupIdentifier,
+ $instance->getHash()
+ );
+ }
+
+ public function testTryTofetchListForMissingOptionsThrowsException() {
+
+ $instance = new PropertyUsageListLookup(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->fetchList();
+ }
+
+ /**
+ * @dataProvider usageCountProvider
+ */
+ public function testfetchListForValidProperty( $expectedCount ) {
+
+ $row = new \stdClass;
+ $row->smw_title = 'Foo';
+ $row->smw_id = 42;
+ $row->usage_count = $expectedCount;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->requestOptions = $this->getMockBuilder( '\SMWRequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyUsageListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $this->requestOptions
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $property = new DIProperty( 'Foo' );
+ $property->id = 42;
+
+ $expected = [
+ $property,
+ $expectedCount
+ ];
+
+ $this->assertEquals(
+ [ $expected ],
+ $result
+ );
+ }
+
+ public function testfetchListForInvalidProperty() {
+
+ $row = new \stdClass;
+ $row->smw_title = '-Foo';
+ $row->smw_id = 42;
+ $row->usage_count = 42;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->requestOptions->limit = 1001;
+
+ $instance = new PropertyUsageListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $this->requestOptions
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $result[0][0]
+ );
+ }
+
+ public function usageCountProvider() {
+
+ $provider[] = [
+ 0
+ ];
+
+ $provider[] = [
+ 1001
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/ProximityPropertyValueLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/ProximityPropertyValueLookupTest.php
new file mode 100644
index 00000000..4fd1f5c6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/ProximityPropertyValueLookupTest.php
@@ -0,0 +1,202 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\DIProperty;
+use SMW\RequestOptions;
+use SMW\SQLStore\Lookup\ProximityPropertyValueLookup;
+use SMW\MediaWiki\Connection\Query;
+use FakeResultWrapper;
+
+/**
+ * @covers \SMW\MediaWiki\Api\Browse\ProximityPropertyValueLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ProximityPropertyValueLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ ProximityPropertyValueLookup::class,
+ new ProximityPropertyValueLookup( $store )
+ );
+ }
+
+ public function testLookup_wpg_property() {
+
+ $row = new \stdClass;
+ $row->smw_title = 'Test';
+ $row->smw_id = 42;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = new Query( $connection );
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( new FakeResultWrapper( [ $row ] ) ) );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID', 'isFixedPropertyTable' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $idTable->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new ProximityPropertyValueLookup(
+ $store
+ );
+
+ $parameters = [
+ 'search' => 'Foo',
+ 'property' => 'Bar'
+ ];
+
+ $instance->lookup(
+ new DIProperty( 'Bar' ),
+ 'Foo',
+ new RequestOptions()
+ );
+
+ $this->assertContains(
+ '[{"OR":"smw_sortkey LIKE %Foo%"},{"OR":"smw_sortkey LIKE %Foo%"},{"OR":"smw_sortkey LIKE %FOO%"}]',
+ $query->__toString()
+ );
+ }
+
+ public function tesLookup_txt_property() {
+
+ $row = new \stdClass;
+ $row->o_hash = 'Test';
+ $row->smw_id = 42;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = new Query( $connection );
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'newQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'query' )
+ ->will( $this->returnValue( new FakeResultWrapper( [ $row ] ) ) );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID', 'isFixedPropertyTable' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $idTable->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( false ) );
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->any() )
+ ->method( 'getLabelField' )
+ ->will( $this->returnValue( 'o_hash' ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new ProximityPropertyValueLookup(
+ $store
+ );
+
+ $parameters = [
+ 'search' => 'Foo',
+ 'property' => 'Text'
+ ];
+
+ $instance->lookup(
+ new DIProperty( '_TEXT' ),
+ 'Foo',
+ new RequestOptions()
+ );
+
+ $this->assertContains(
+ '[{"OR":"o_hash LIKE %Foo%"},{"OR":"o_hash LIKE %Foo%"},{"OR":"o_hash LIKE %FOO%"},{"AND":"p_id=42"}]',
+ $query->__toString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/RedirectTargetLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/RedirectTargetLookupTest.php
new file mode 100644
index 00000000..e3317c5c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/RedirectTargetLookupTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\Lookup\RedirectTargetLookup;
+
+/**
+ * @covers \SMW\SQLStore\Lookup\RedirectTargetLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class RedirectTargetLookupTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\RedirectTargetLookup',
+ new RedirectTargetLookup( $store, $circularReferenceGuard )
+ );
+ }
+
+ public function testFindRedirectTargetOnValidDataItem() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getRedirectTarget' );
+
+ $circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $circularReferenceGuard->expects( $this->atLeastOnce() )
+ ->method( 'isCircular' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new RedirectTargetLookup(
+ $store,
+ $circularReferenceGuard
+ );
+
+ $instance->findRedirectTarget( DIWikiPage::newFromText( 'Foo' ) );
+ }
+
+ public function testFindRedirectTargetOnInvalidDataItem() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->never() )
+ ->method( 'getRedirectTarget' );
+
+ $circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $circularReferenceGuard->expects( $this->never() )
+ ->method( 'isCircular' );
+
+ $instance = new RedirectTargetLookup(
+ $store,
+ $circularReferenceGuard
+ );
+
+ $instance->findRedirectTarget( 'foo' );
+ }
+
+ public function testFindRedirectTargetOnSelfReferencedDataItem() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->never() )
+ ->method( 'getRedirectTarget' );
+
+ $circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $circularReferenceGuard->expects( $this->atLeastOnce() )
+ ->method( 'isCircular' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new RedirectTargetLookup(
+ $store,
+ $circularReferenceGuard
+ );
+
+ $instance->findRedirectTarget( DIWikiPage::newFromText( 'Foo' ) );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UndeclaredPropertyListLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UndeclaredPropertyListLookupTest.php
new file mode 100644
index 00000000..4766e9f2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UndeclaredPropertyListLookupTest.php
@@ -0,0 +1,285 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\DIProperty;
+use SMW\RequestOptions;
+use SMW\SQLStore\Lookup\UndeclaredPropertyListLookup;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\Lookup\UndeclaredPropertyListLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class UndeclaredPropertyListLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $requestOptions;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestOptions = $this->getMockBuilder( '\SMWRequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestOptions->expects( $this->any() )
+ ->method( 'getExtraConditions' )
+ ->will( $this->returnValue( [] ) );
+ }
+
+ public function testCanConstruct() {
+
+ $defaultPropertyType = '_foo';
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\UndeclaredPropertyListLookup',
+ new UndeclaredPropertyListLookup( $this->store, $defaultPropertyType, null )
+ );
+ }
+
+ public function testListLookupInterfaceMethodAccess() {
+
+ $defaultPropertyType = '_foo';
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType,
+ $this->requestOptions
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getTimestamp()
+ );
+
+ $this->assertFalse(
+ $instance->isFromCache()
+ );
+
+ $this->assertContains(
+ 'UndeclaredPropertyListLookup',
+ $instance->getHash()
+ );
+ }
+
+ public function testNullRequestOptionsThrowsException() {
+
+ $defaultPropertyType = '_foo';
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->fetchList();
+ }
+
+ public function testInvalidTableIdThrowsException() {
+
+ $defaultPropertyType = '_foo';
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType,
+ $this->requestOptions
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->fetchList();
+ }
+
+ public function testLookupIdentifierChangedByRequestOptions() {
+
+ $defaultPropertyType = '_foo';
+ $requestOptions = new RequestOptions();
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType,
+ $requestOptions
+ );
+
+ $lookupIdentifier = $instance->getHash();
+ $requestOptions->limit = 100;
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType,
+ $requestOptions
+ );
+
+
+ $this->assertNotSame(
+ $lookupIdentifier,
+ $instance->getHash()
+ );
+ }
+
+ public function testfetchListForValidProperty() {
+
+ $row = new \stdClass;
+ $row->smw_title = 'Foo';
+ $row->count = 42;
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->once() )
+ ->method( 'findTypeTableId' )
+ ->with( $this->equalTo( '_foo' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => $tableDefinition ] ) );
+
+ $defaultPropertyType = '_foo';
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType,
+ $this->requestOptions
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $expected = [
+ new DIProperty( 'Foo' ),
+ 42
+ ];
+
+ $this->assertEquals(
+ [ $expected ],
+ $result
+ );
+ }
+
+ public function testfetchListForInvalidProperty() {
+
+ $row = new \stdClass;
+ $row->smw_title = '-Foo';
+ $row->count = 42;
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->once() )
+ ->method( 'findTypeTableId' )
+ ->with( $this->equalTo( '_foo' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => $tableDefinition ] ) );
+
+ $defaultPropertyType = '_foo';
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType,
+ $this->requestOptions
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $result[0][0]
+ );
+ }
+
+ public function testfetchListForFixedPropertyTable() {
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableDefinition->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->never() )
+ ->method( 'select' );
+
+ $this->store->expects( $this->once() )
+ ->method( 'findTypeTableId' )
+ ->with( $this->equalTo( '_foo' ) )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => $tableDefinition ] ) );
+
+ $defaultPropertyType = '_foo';
+
+ $instance = new UndeclaredPropertyListLookup(
+ $this->store,
+ $defaultPropertyType,
+ $this->requestOptions
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $this->assertEmpty(
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UnusedPropertyListLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UnusedPropertyListLookupTest.php
new file mode 100644
index 00000000..01599519
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UnusedPropertyListLookupTest.php
@@ -0,0 +1,217 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\DIProperty;
+use SMW\RequestOptions;
+use SMW\SQLStore\Lookup\UnusedPropertyListLookup;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\Lookup\UnusedPropertyListLookup
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class UnusedPropertyListLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $propertyStatisticsStore;
+ private $requestOptions;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestOptions = $this->getMockBuilder( '\SMWRequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\UnusedPropertyListLookup',
+ new UnusedPropertyListLookup( $this->store, $this->propertyStatisticsStore, null )
+ );
+ }
+
+ public function testListLookupInterfaceMethodAccess() {
+
+ $instance = new UnusedPropertyListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $this->requestOptions
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getTimestamp()
+ );
+
+ $this->assertFalse(
+ $instance->isFromCache()
+ );
+
+ $this->assertContains(
+ 'UnusedPropertyListLookup',
+ $instance->getHash()
+ );
+ }
+
+ public function testLookupIdentifierChangedByRequestOptions() {
+
+ $requestOptions = new RequestOptions();
+
+ $instance = new UnusedPropertyListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $requestOptions
+ );
+
+ $lookupIdentifier = $instance->getHash();
+
+ $requestOptions->limit = 100;
+
+ $instance = new UnusedPropertyListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $requestOptions
+ );
+
+ $this->assertNotSame(
+ $lookupIdentifier,
+ $instance->getHash()
+ );
+ }
+
+ public function testTryTofetchListForMissingOptionsThrowsException() {
+
+ $instance = new UnusedPropertyListLookup(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->fetchList();
+ }
+
+ public function testfetchListForValidProperty() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getIdTable' ] )
+ ->getMock();
+
+ $row = new \stdClass;
+ $row->smw_title = 'Foo';
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $instance = new UnusedPropertyListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $this->requestOptions
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $expected = [
+ new DIProperty( 'Foo' )
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $result
+ );
+ }
+
+ public function testfetchListForInvalidProperty() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getIdTable' ] )
+ ->getMock();
+
+ $row = new \stdClass;
+ $row->smw_title = '-Foo';
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'ORDER BY' => 'smw_sort', 'LIMIT' => 1001, 'OFFSET' => 0 ] ),
+ $this->anything() )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $requestOptions = $this->getMockBuilder( '\SMWRequestOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->requestOptions->limit = 1001;
+
+ $instance = new UnusedPropertyListLookup(
+ $this->store,
+ $this->propertyStatisticsStore,
+ $this->requestOptions
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $result[0]
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UsageStatisticsListLookupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UsageStatisticsListLookupTest.php
new file mode 100644
index 00000000..643ba3b9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/Lookup/UsageStatisticsListLookupTest.php
@@ -0,0 +1,184 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Lookup;
+
+use SMW\SQLStore\Lookup\UsageStatisticsListLookup;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\Lookup\UsageStatisticsListLookup
+ * @group semantic-mediawiki
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class UsageStatisticsListLookupTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $propertyStatisticsStore;
+ private $requestOptions;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\UsageStatisticsListLookup',
+ new UsageStatisticsListLookup( $this->store, $this->propertyStatisticsStore )
+ );
+ }
+
+ public function testListLookupInterfaceMethodAccess() {
+
+ $instance = new UsageStatisticsListLookup(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getTimestamp()
+ );
+
+ $this->assertFalse(
+ $instance->isFromCache()
+ );
+
+ $this->assertEquals(
+ 'statistics-lookup',
+ $instance->getHash()
+ );
+ }
+
+ public function testfetchListForInvalidTableThrowsException() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( new \FakeResultWrapper( [] ) ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( 'Bar' ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => 'throwExceptionForMismatch' ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new UsageStatisticsListLookup(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->fetchList();
+ }
+
+ /**
+ * @dataProvider bySegmentDataProvider
+ */
+ public function testfetchList( $segment, $type ) {
+
+ $row = new \stdClass;
+ $row->o_hash = 42;
+ $row->count = 1001;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'select' )
+ ->will( $this->returnValue( new \FakeResultWrapper( [ $row ] ) ) );
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdFetcher = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSMWPropertyID' ] )
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdFetcher ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => $tableDefinition ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->propertyStatisticsStore->expects( $this->any() )
+ ->method( 'getUsageCount' )
+ ->will( $this->returnValue( 54 ) );
+
+ $instance = new UsageStatisticsListLookup(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $result = $instance->fetchList();
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+
+ $this->assertArrayHasKey(
+ $segment,
+ $result
+ );
+
+ $this->assertInternalType(
+ $type,
+ $result[$segment]
+ );
+ }
+
+ public function bySegmentDataProvider() {
+ return [
+ [ 'OWNPAGE', 'integer' ],
+ [ 'QUERY', 'integer' ],
+ [ 'QUERYSIZE', 'integer' ],
+ [ 'QUERYFORMATS', 'array' ],
+ [ 'CONCEPTS', 'integer' ],
+ [ 'SUBOBJECTS', 'integer' ],
+ [ 'DECLPROPS', 'integer' ],
+ [ 'USEDPROPS', 'integer' ],
+ [ 'TOTALPROPS', 'integer' ],
+ [ 'PROPUSES', 'integer' ],
+ [ 'ERRORUSES', 'integer' ],
+ [ 'DELETECOUNT', 'integer' ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyStatisticsStoreTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyStatisticsStoreTest.php
new file mode 100644
index 00000000..3deed821
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyStatisticsStoreTest.php
@@ -0,0 +1,378 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\PropertyStatisticsStore;
+use SMW\SQLStore\SQLStore;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\PropertyStatisticsStore
+ * @group semantic-mediawiki
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class PropertyStatisticsStoreTest extends MwDBaseUnitTestCase {
+
+ use PHPUnitCompat;
+
+ protected $statsTable = null;
+
+ /**
+ * On the Windows platform pow( 2 , 31 ) returns with
+ * "MWException: The value to add must be a positive integer" therefore
+ * return true if this test runs on Windows
+ *
+ * @return boolean
+ */
+ private function isWinOS() {
+ return strtoupper( substr( PHP_OS, 0, 3 ) ) === 'WIN';
+ }
+
+ public function testDeleteAll() {
+
+ $statsTable = new PropertyStatisticsStore(
+ $this->getStore()->getConnection( 'mw.db' )
+ );
+
+ $this->assertTrue( $statsTable->deleteAll() !== false );
+ $this->assertTrue( $statsTable->deleteAll() !== false );
+
+ $statsTable->insertUsageCount( 1, 1 );
+
+ $this->assertTrue( $statsTable->deleteAll() !== false );
+
+ $this->assertTrue( $statsTable->getUsageCounts( [ 1, 2 ] ) === [] );
+ }
+
+ public function usageCountProvider() {
+ $usageCounts = [];
+
+ $usageCounts[] = [ 1, 0 ];
+ $usageCounts[] = [ 2, 1 ];
+
+ for ( $propId = 3; $propId <= 42; $propId++ ) {
+ $usageCounts[] = [ $propId, mt_rand( 0, 100000 ) ];
+ }
+
+ $usageCounts[] = [ 9001, $this->isWinOS() ? pow( 2, 30 ) : pow( 2, 31 ) ];
+
+ return $usageCounts;
+ }
+
+ /**
+ * @return \SMW\Store\PropertyStatisticsStore
+ */
+ protected function getTable() {
+ if ( $this->statsTable === null ) {
+
+ $this->statsTable = new PropertyStatisticsStore(
+ $this->getStore()->getConnection( 'mw.db' )
+ );
+
+ $this->assertTrue( $this->statsTable->deleteAll() !== false );
+ }
+
+ return $this->statsTable;
+ }
+
+ /**
+ * @dataProvider usageCountProvider
+ */
+ public function testGetUsageCount( $propId, $usageCount ) {
+
+ $table = $this->getTable();
+
+ $table->insertUsageCount( $propId, $usageCount );
+
+ $this->assertEquals(
+ $usageCount,
+ $table->getUsageCount( $propId )
+ );
+ }
+
+ public function testAddToUsageCountWithInvalidCountThrowsException() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyStatisticsStore(
+ $connection,
+ 'foo'
+ );
+
+ $this->setExpectedException( '\SMW\SQLStore\Exception\PropertyStatisticsInvalidArgumentException');
+ $instance->addToUsageCount( 12, 'foo' );
+ }
+
+ public function testAddToUsageCountWithInvalidIdThrowsException() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new PropertyStatisticsStore(
+ $connection
+ );
+
+ $this->setExpectedException( '\SMW\SQLStore\Exception\PropertyStatisticsInvalidArgumentException');
+ $instance->addToUsageCount( 'Foo', 12 );
+ }
+
+ /**
+ * @dataProvider usageCountProvider
+ *
+ * @param int $propId
+ * @param int $usageCount
+ */
+ public function testInsertUsageCount( $propId, $usageCount ) {
+
+ $table = $this->getTable();
+
+ $this->assertTrue( $table->insertUsageCount( $propId, $usageCount ) );
+
+ $usageCounts = $table->getUsageCounts( [ $propId ] );
+
+ $this->assertArrayHasKey( $propId, $usageCounts );
+ $this->assertEquals( $usageCount, $usageCounts[$propId] );
+
+ $change = mt_rand( max( -100, -$usageCount ), 100 );
+
+ $this->assertTrue( $table->addToUsageCount( $propId, $change ) !== false );
+
+ $usageCounts = $table->getUsageCounts( [ $propId ] );
+
+ $this->assertArrayHasKey( $propId, $usageCounts );
+ $this->assertEquals( $usageCount + $change, $usageCounts[$propId], 'Testing addToUsageCount with ' . $change );
+ }
+
+ public function testAddToUsageCounts() {
+
+ $statsTable = new PropertyStatisticsStore(
+ $this->getStore()->getConnection( 'mw.db' )
+ );
+
+ $this->assertTrue( $statsTable->deleteAll() !== false );
+
+ $counts = [
+ 1 => 42,
+ 2 => 0,
+ 9001 => 9001,
+ 9002 => $this->isWinOS() ? pow( 2, 30 ) : pow( 2, 31 ),
+ 9003 => 1,
+ ];
+
+ foreach ( $counts as $propId => $count ) {
+ $this->assertTrue( $statsTable->insertUsageCount( $propId, $count ) !== false );
+ }
+
+ $additions = [
+ 2 => 42,
+ 9001 => -9000,
+ 9003 => 0,
+ ];
+
+ $this->assertTrue(
+ $statsTable->addToUsageCounts( $additions ) !== false
+ );
+
+ foreach ( $additions as $propId => $addition ) {
+ $counts[$propId] += $addition;
+ }
+
+ $this->assertEquals(
+ $counts,
+ $statsTable->getUsageCounts( array_keys( $counts ) )
+ );
+ }
+
+ public function testAddToUsageCountsOnTransactionIdle() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) {
+ return call_user_func( $callback );
+ }
+ ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'update' );
+
+ $instance = new PropertyStatisticsStore(
+ $connection
+ );
+
+ $additions = [
+ 2 => 42,
+ 9001 => -9000,
+ 9003 => 0,
+ ];
+
+ $instance->waitOnTransactionIdle();
+
+ $this->assertTrue(
+ $instance->addToUsageCounts( $additions )
+ );
+ }
+
+ public function testAddToUsageCountsWillNotWaitOnTransactionIdleWhenCommandLineModeIsActive() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->never() )
+ ->method( 'onTransactionIdle' );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'update' );
+
+ $instance = new PropertyStatisticsStore(
+ $connection
+ );
+
+ $additions = [
+ 2 => 42,
+ 9001 => -9000,
+ 9003 => 0,
+ ];
+
+ $instance->isCommandLineMode( true );
+ $instance->waitOnTransactionIdle();
+
+ $instance->addToUsageCounts( $additions );
+ }
+
+ public function testInsertUsageCountWithArrayValue() {
+
+ $tableName = 'Foo';
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'insert' )
+ ->with(
+ $this->stringContains( SQLStore::PROPERTY_STATISTICS_TABLE ),
+ $this->equalTo(
+ [
+ 'usage_count' => 1,
+ 'null_count' => 9999,
+ 'p_id' => 42
+ ] ),
+ $this->anything() );
+
+
+ $instance = new PropertyStatisticsStore(
+ $connection
+ );
+
+ $instance->insertUsageCount( 42, [ 1, 9999 ] );
+ }
+
+ public function testAddToUsageCountsWithArrayValue() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'update' )
+ ->with(
+ $this->stringContains( SQLStore::PROPERTY_STATISTICS_TABLE ),
+ $this->equalTo(
+ [
+ 'usage_count = usage_count + 1',
+ 'null_count = null_count + 9999'
+ ] ),
+ $this->equalTo(
+ [
+ 'p_id' => 42
+ ] ),
+ $this->anything() );
+
+ $instance = new PropertyStatisticsStore(
+ $connection
+ );
+
+ $instance->addToUsageCounts( [ 42 => [ 'usage' => 1, 'null' => 9999 ] ] );
+ }
+
+ public function testSetUsageCountWithArrayValue() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'update' )
+ ->with(
+ $this->stringContains( SQLStore::PROPERTY_STATISTICS_TABLE ),
+ $this->equalTo(
+ [
+ 'usage_count' => 1,
+ 'null_count' => 9999
+ ] ),
+ $this->equalTo(
+ [
+ 'p_id' => 42
+ ] ),
+ $this->anything() );
+
+ $instance = new PropertyStatisticsStore(
+ $connection
+ );
+
+ $instance->setUsageCount( 42, [ 1, 9999 ] );
+ }
+
+ public function testUpsertOnInsertUsageCount() {
+
+ $error = $this->getMockBuilder( '\DBQueryError' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'insert' )
+ ->will( $this->throwException( $error ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'update' )
+ ->with(
+ $this->stringContains( SQLStore::PROPERTY_STATISTICS_TABLE ),
+ $this->equalTo(
+ [
+ 'usage_count' => 12,
+ 'null_count' => 0
+ ] ),
+ $this->equalTo( [ 'p_id' => 42 ] ),
+ $this->anything() );
+
+ $instance = new PropertyStatisticsStore(
+ $connection
+ );
+
+ $instance->insertUsageCount( 42, 12 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionBuilderTest.php
new file mode 100644
index 00000000..ce184204
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionBuilderTest.php
@@ -0,0 +1,182 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\PropertyTableDefinitionBuilder;
+use SMW\Tests\Utils\MwHooksHandler;
+use SMWDataItem as DataItem;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableDefinitionBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class PropertyTableDefinitionBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $propertyTypeFinder;
+ private $mwHooksHandler;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mwHooksHandler = new MwHooksHandler();
+ $this->mwHooksHandler->deregisterListedHooks();
+
+ $this->propertyTypeFinder = $this->getMockBuilder( '\SMW\SQLStore\PropertyTypeFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+
+ $this->mwHooksHandler->restoreListedHooks();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $dataItems = [];
+ $specials = [];
+ $fixed = [];
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyTableDefinitionBuilder',
+ new PropertyTableDefinitionBuilder( $this->propertyTypeFinder )
+ );
+ }
+
+ public function testDataItemTypes() {
+
+ $dataItems = [ DataItem::TYPE_NUMBER => 'smw_di_number' ];
+ $specials = [];
+ $fixed = [];
+
+ $instance = new PropertyTableDefinitionBuilder(
+ $this->propertyTypeFinder
+ );
+
+ $instance->doBuild(
+ $dataItems,
+ $specials,
+ $fixed
+ );
+
+ $definition = $instance->newTableDefinition(
+ DataItem::TYPE_NUMBER, 'smw_di_number'
+ );
+
+ $expected = [
+ 'smw_di_number' => $definition
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getTableDefinitions()
+ );
+ }
+
+ public function testUserDefinedFixedPropertyDeclaration() {
+
+ $propertyKey = 'foo bar';
+ $expectedKey = 'Foo_bar';
+
+ $dataItems = [];
+ $specials = [];
+ $fixed = [ $propertyKey ];
+
+ $this->propertyTypeFinder->expects( $this->any() )
+ ->method( 'findTypeID' )
+ ->will( $this->returnValue( '_num' ) );
+
+ $instance = new PropertyTableDefinitionBuilder(
+ $this->propertyTypeFinder
+ );
+
+ $instance->doBuild(
+ $dataItems,
+ $specials,
+ $fixed
+ );
+
+ $tableName = $instance->createHashedTableNameFrom( $expectedKey );
+ $definition = $instance->newTableDefinition( DataItem::TYPE_NUMBER, $tableName, $expectedKey );
+
+ $expected = [
+ 'definition' => [ $tableName => $definition ],
+ 'tableId' => [ $expectedKey => $tableName, '_SKEY' => null ]
+ ];
+
+ $this->assertEquals(
+ $expected['definition'],
+ $instance->getTableDefinitions()
+ );
+
+ $this->assertEquals(
+ $expected['tableId'],
+ $instance->getFixedPropertyTableIds()
+ );
+ }
+
+ public function testSpecialProperties() {
+
+ $propertyKey = '_MDAT';
+
+ $dataItems = [];
+ $specials = [ $propertyKey ];
+ $fixed = [];
+
+ $instance = new PropertyTableDefinitionBuilder(
+ $this->propertyTypeFinder
+ );
+
+ $instance->doBuild(
+ $dataItems,
+ $specials,
+ $fixed
+ );
+
+ $tableName = $instance->getTablePrefix() . strtolower( $propertyKey );
+ $definition = $instance->newTableDefinition( DataItem::TYPE_TIME, $tableName, $propertyKey );
+ $expected = [ $tableName => $definition ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getTableDefinitions()
+ );
+ }
+
+ public function testRedirects() {
+
+ $propertyKey = '_REDI';
+
+ $dataItems = [];
+ $specials = [ $propertyKey ];
+ $fixed = [];
+
+ $instance = new PropertyTableDefinitionBuilder(
+ $this->propertyTypeFinder
+ );
+
+ $instance->doBuild(
+ $dataItems,
+ $specials,
+ $fixed
+ );
+
+ $tableName = $instance->getTablePrefix() . strtolower( $propertyKey );
+ $definition = $instance->newTableDefinition( DataItem::TYPE_WIKIPAGE, $tableName, $propertyKey );
+
+ $expected = [ $tableName => $definition ];
+ $tableDefinitions = $instance->getTableDefinitions();
+
+ $this->assertFalse(
+ $tableDefinitions[$tableName]->usesIdSubject()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionTest.php
new file mode 100644
index 00000000..07233596
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableDefinitionTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\PropertyTableDefinition;
+use SMW\StoreFactory;
+use SMWDataItem;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableDefinition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class PropertyTableDefinitionTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyTableDefinition',
+ new PropertyTableDefinition( 'foo', 'bar' )
+ );
+ }
+
+ public function testGetters() {
+
+ $diType = SMWDataItem::TYPE_NUMBER;
+ $name = 'smw_di_number';
+
+ $instance = new PropertyTableDefinition( $diType, $name );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getFields( StoreFactory::getStore( 'SMWSQLStore3' ) )
+ );
+
+ $this->assertEquals(
+ $diType,
+ $instance->getDiType()
+ );
+
+ $this->assertEquals(
+ $name,
+ $instance->getName()
+ );
+ }
+
+ public function testIdSubject() {
+
+ $instance = new PropertyTableDefinition( 'foo', 'bar' );
+ $instance->setUsesIdSubject( false );
+
+ $this->assertFalse(
+ $instance->usesIdSubject()
+ );
+ }
+
+ public function testGetFixedProperty() {
+
+ $instance = new PropertyTableDefinition( 'foo', 'bar' );
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+ $instance->getFixedProperty();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceDisposerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceDisposerTest.php
new file mode 100644
index 00000000..7cb86c00
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceDisposerTest.php
@@ -0,0 +1,362 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\PropertyTableIdReferenceDisposer;
+use SMW\SQLStore\SQLStore;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableIdReferenceDisposer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class PropertyTableIdReferenceDisposerTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getDataItemById' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getDataItemById' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( 'Foo' ) ) );
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $jobQueueGroup = $this->getMockBuilder( '\JobQueueGroup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobQueueGroup->expects( $this->any() )
+ ->method( 'lazyPush' );
+
+ $this->testEnvironment->registerObject( 'JobQueueGroup', $jobQueueGroup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertyTableIdReferenceDisposer::class,
+ new PropertyTableIdReferenceDisposer( $this->store )
+ );
+ }
+
+ public function testIsDisposable() {
+
+ $propertyTableIdReferenceFinder = $connection = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableIdReferenceFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableIdReferenceFinder->expects( $this->any() )
+ ->method( 'hasResidualReferenceForId' )
+ ->with( $this->equalTo( 42 ) )
+ ->will( $this->returnValue( false ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTableIdReferenceFinder' )
+ ->will( $this->returnValue( $propertyTableIdReferenceFinder ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $this->store
+ );
+
+ $this->assertTrue(
+ $instance->isDisposable( 42 )
+ );
+ }
+
+ public function testTryToRemoveOutdatedEntryFromIDTable() {
+
+ $tableDefinition = $connection = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableIdReferenceFinder = $connection = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableIdReferenceFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $connection->expects( $this->at( 0 ) )
+ ->method( 'delete' )
+ ->with( $this->equalTo( \SMW\SQLStore\SQLStore::ID_TABLE ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $tableDefinition ] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTableIdReferenceFinder' )
+ ->will( $this->returnValue( $propertyTableIdReferenceFinder ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $this->store
+ );
+
+ $instance->removeOutdatedEntityReferencesById( 42 );
+ }
+
+ public function testCleanUpTableEntriesFor() {
+
+ $tableDefinition = $connection = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableDefinition->expects( $this->once() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $connection->expects( $this->at( 3 ) )
+ ->method( 'delete' )
+ ->with( $this->equalTo( \SMW\SQLStore\SQLStore::ID_TABLE ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $tableDefinition ] ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $this->store
+ );
+
+ $instance->cleanUpTableEntriesById( 42 );
+ }
+
+ public function testCanConstructOutdatedEntitiesResultIterator() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $this->store
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Iterators\ResultIterator',
+ $instance->newOutdatedEntitiesResultIterator()
+ );
+ }
+
+ public function testCleanUpTableEntriesByRow() {
+
+ $row = new \stdClass;
+ $row->smw_id = 42;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'delete' );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $this->store
+ );
+
+ $instance->cleanUpTableEntriesByRow( $row );
+ }
+
+ public function testCleanUpOnTransactionIdle() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) {
+ return call_user_func( $callback );
+ }
+ ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'delete' );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $this->store
+ );
+
+ $instance->waitOnTransactionIdle();
+ $instance->cleanUpTableEntriesById( 42 );
+ }
+
+ public function testCleanUpOnTransactionIdleAvoidOnSubobject() {
+
+ if ( !method_exists( '\PHPUnit_Framework_MockObject_Builder_InvocationMocker', 'withConsecutive' ) ) {
+ $this->markTestSkipped( 'PHPUnit_Framework_MockObject_Builder_InvocationMocker::withConsecutive requires PHPUnit 5.7+.' );
+ }
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getDataItemById' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getDataItemById' )
+ ->will( $this->returnValue( new DIWikiPage( 'Foo', NS_MAIN, '', 'Bar' ) ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) {
+ return $callback();
+ } ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'delete' )
+ ->withConsecutive(
+ [ $this->equalTo( SQLStore::ID_TABLE ) ],
+ [ $this->equalTo( SQLStore::PROPERTY_STATISTICS_TABLE ) ],
+ [ $this->equalTo( SQLStore::QUERY_LINKS_TABLE ) ],
+ [ $this->equalTo( SQLStore::QUERY_LINKS_TABLE ) ],
+ [ $this->equalTo( SQLStore::FT_SEARCH_TABLE ) ]
+ );
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $store
+ );
+
+ $instance->waitOnTransactionIdle();
+ $instance->cleanUpTableEntriesById( 42 );
+ }
+
+ public function testCleanUp_Redirect() {
+
+ if ( !method_exists( '\PHPUnit_Framework_MockObject_Builder_InvocationMocker', 'withConsecutive' ) ) {
+ $this->markTestSkipped( 'PHPUnit_Framework_MockObject_Builder_InvocationMocker::withConsecutive requires PHPUnit 5.7+.' );
+ }
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getDataItemById' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getDataItemById' )
+ ->will( $this->returnValue( new DIWikiPage( 'Foo', NS_MAIN, SMW_SQL3_SMWREDIIW ) ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // No SQLStore::ID_TABLE
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'delete' )
+ ->withConsecutive(
+ [ $this->equalTo( SQLStore::PROPERTY_STATISTICS_TABLE ) ],
+ [ $this->equalTo( SQLStore::QUERY_LINKS_TABLE ) ],
+ [ $this->equalTo( SQLStore::QUERY_LINKS_TABLE ) ],
+ [ $this->equalTo( SQLStore::FT_SEARCH_TABLE ) ]
+ );
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new PropertyTableIdReferenceDisposer(
+ $store
+ );
+
+ $instance->cleanUpTableEntriesById( 42 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceFinderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceFinderTest.php
new file mode 100644
index 00000000..6a5fa782
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableIdReferenceFinderTest.php
@@ -0,0 +1,209 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\DIProperty;
+use SMW\SQLStore\PropertyTableIdReferenceFinder;
+use SMW\SQLStore\SQLStore;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableIdReferenceFinder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class PropertyTableIdReferenceFinderTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyTableIdReferenceFinder',
+ new PropertyTableIdReferenceFinder( $this->store )
+ );
+ }
+
+ public function testFindAtLeastOneActiveReferenceById() {
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableDefinition->expects( $this->atLeastOnce() )
+ ->method( 'getFields' )
+ ->will( $this->returnValue( [ 'o_id' => 42 ] ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $tableDefinition ] ) );
+
+ $instance = new PropertyTableIdReferenceFinder(
+ $this->store
+ );
+
+ $this->assertFalse(
+ $instance->findAtLeastOneActiveReferenceById( 42 )
+ );
+ }
+
+ public function testTryToFindAtLeastOneReferenceForProperty() {
+
+ $idTable = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableDefinition = $connection = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableDefinition->expects( $this->once() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $tableDefinition ] ) );
+
+ $instance = new PropertyTableIdReferenceFinder(
+ $this->store
+ );
+
+ $instance->tryToFindAtLeastOneReferenceForProperty( new DIProperty( 'Foo' ) );
+ }
+
+ public function testHasResidualPropertyTableReference() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new PropertyTableIdReferenceFinder(
+ $this->store
+ );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->hasResidualPropertyTableReference( 42 )
+ );
+ }
+
+ public function testHasResidualReferenceFor() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new PropertyTableIdReferenceFinder(
+ $this->store
+ );
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->hasResidualReferenceForId( 42 )
+ );
+ }
+
+ public function testSearchAllTablesToFindAtLeastOneReferenceById() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new PropertyTableIdReferenceFinder(
+ $this->store
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->searchAllTablesToFindAtLeastOneReferenceById( 42 )
+ );
+ }
+
+ public function testConfirmBorderId() {
+
+ $instance = new PropertyTableIdReferenceFinder(
+ $this->store
+ );
+
+ $this->assertTrue(
+ $instance->hasResidualReferenceForId( SQLStore::FIXED_PROPERTY_ID_UPPERBOUND )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableInfoFetcherTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableInfoFetcherTest.php
new file mode 100644
index 00000000..bf72f7f9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableInfoFetcherTest.php
@@ -0,0 +1,208 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\DIProperty;
+use SMW\SQLStore\PropertyTableInfoFetcher;
+use SMWDataItem as DataItem;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableInfoFetcher
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class PropertyTableInfoFetcherTest extends \PHPUnit_Framework_TestCase {
+
+ private $propertyTypeFinder;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->propertyTypeFinder = $this->getMockBuilder( '\SMW\SQLStore\PropertyTypeFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyTableInfoFetcher',
+ new PropertyTableInfoFetcher( $this->propertyTypeFinder )
+ );
+ }
+
+ public function testGetPropertyTableDefinitions() {
+
+ $instance = new PropertyTableInfoFetcher(
+ $this->propertyTypeFinder
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getPropertyTableDefinitions()
+ );
+
+ $instance->clearCache();
+ }
+
+ /**
+ * @dataProvider propertyProvider
+ */
+ public function testFindTableIdForProperty( $property, $expected ) {
+
+ $property = DIProperty::newFromUserLabel( $property );
+
+ $instance = new PropertyTableInfoFetcher(
+ $this->propertyTypeFinder
+ );
+
+ $instance->setCustomSpecialPropertyList(
+ [ '_MDAT', '_MEDIA', '_MIME' ]
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->findTableIdForProperty( $property )
+ );
+ }
+
+ /**
+ * @dataProvider defaultDiTypeProvider
+ */
+ public function testFindTableIdForDataItemTypeId( $diType, $expected ) {
+
+ $instance = new PropertyTableInfoFetcher(
+ $this->propertyTypeFinder
+ );
+
+ $instance->setCustomSpecialPropertyList(
+ [ '_MDAT', '_MEDIA', '_MIME' ]
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->findTableIdForDataItemTypeId( $diType )
+ );
+ }
+
+ /**
+ * @dataProvider dataTypeProvider
+ */
+ public function testFindTableIdForDataTypeTypeId( $dataType, $expected ) {
+
+ $instance = new PropertyTableInfoFetcher(
+ $this->propertyTypeFinder
+ );
+
+ $instance->setCustomSpecialPropertyList(
+ [ '_MDAT', '_MEDIA', '_MIME' ]
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->findTableIdForDataTypeTypeId( $dataType )
+ );
+ }
+
+ public function propertyProvider() {
+
+ $provider = [];
+
+ // Pre-defined property
+ $provider = [
+ [ '_MDAT', 'smw_fpt_mdat' ],
+ [ '_CDAT', 'smw_di_time' ],
+ [ '_NEWP', 'smw_di_bool' ],
+ [ '_LEDT', 'smw_di_wikipage' ],
+ [ '_MIME', 'smw_fpt_mime' ],
+ [ '_MEDIA', 'smw_fpt_media' ],
+ [ '_TYPE', 'smw_fpt_type' ],
+ [ '_UNIT', 'smw_fpt_unit' ],
+ [ '_CONV', 'smw_fpt_conv' ],
+ [ '_PVAL', 'smw_fpt_pval' ],
+ [ '_LIST', 'smw_fpt_list' ],
+ [ '_SERV', 'smw_fpt_serv' ],
+ [ '_ASK', 'smw_fpt_ask' ],
+ [ '_ASKDE', 'smw_fpt_askde' ],
+ [ '_ASKSI', 'smw_fpt_asksi' ],
+ [ '_ASKFO', 'smw_fpt_askfo' ],
+ [ '_ASKST', 'smw_fpt_askst' ],
+ [ '_ASKDU', 'smw_fpt_askdu' ],
+ [ '_SUBP', 'smw_fpt_subp' ],
+ [ '_SUBC', 'smw_fpt_subc' ],
+ [ '_INST', 'smw_fpt_inst' ],
+ [ '_REDI', 'smw_fpt_redi' ],
+ [ '_SOBJ', 'smw_fpt_sobj' ],
+ [ '_IMPO', 'smw_fpt_impo' ],
+ [ '_URI', 'smw_fpt_uri' ],
+ [ '_CONC', 'smw_fpt_conc' ],
+ ];
+
+ $provider[] = [
+ 'Modification date',
+ 'smw_fpt_mdat'
+ ];
+
+ // User-defined property
+ $provider[] = [
+ 'Foo',
+ 'smw_di_wikipage'
+ ];
+
+ return $provider;
+ }
+
+ public function defaultDiTypeProvider() {
+
+ $provider = [];
+
+ // Known
+ $provider = [
+ [ DataItem::TYPE_NUMBER, 'smw_di_number' ],
+ [ DataItem::TYPE_BLOB,'smw_di_blob' ],
+ [ DataItem::TYPE_BOOLEAN, 'smw_di_bool' ],
+ [ DataItem::TYPE_URI, 'smw_di_uri' ],
+ [ DataItem::TYPE_TIME, 'smw_di_time'],
+ [ DataItem::TYPE_GEO, 'smw_di_coords' ],
+ [ DataItem::TYPE_WIKIPAGE, 'smw_di_wikipage' ],
+ [ DataItem::TYPE_CONCEPT, '' ],
+ ];
+
+ // Unknown
+ $provider[] = [
+ 'Foo',
+ ''
+ ];
+
+ return $provider;
+ }
+
+ public function dataTypeProvider() {
+
+ $provider = [];
+
+ // Known
+ $provider = [
+ [ '_num', 'smw_di_number' ],
+ [ '_txt','smw_di_blob' ],
+ [ '_boo', 'smw_di_bool' ],
+ [ '_uri', 'smw_di_uri' ],
+ [ '_dat', 'smw_di_time'],
+ [ '_geo', 'smw_di_coords' ],
+ [ '_wpg', 'smw_di_wikipage' ],
+ ];
+
+ // Unknown
+ $provider[] = [
+ 'Foo',
+ ''
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowDifferTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowDifferTest.php
new file mode 100644
index 00000000..fedb9700
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowDifferTest.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SQLStore\ChangeOp\ChangeOp;
+use SMW\SQLStore\PropertyTableRowDiffer;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableRowDiffer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class PropertyTableRowDifferTest extends \PHPUnit_Framework_TestCase {
+
+ private $propertyTableRowMapper;
+
+ protected function setUp() {
+
+ $this->propertyTableRowMapper = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableRowMapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyTableRowMapper->expects( $this->any() )
+ ->method( 'mapToRows' )
+ ->will( $this->returnValue( [ [], [], [], [] ] ) );
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyTableRowDiffer',
+ new PropertyTableRowDiffer( $store, $this->propertyTableRowMapper )
+ );
+ }
+
+ public function testComputeTableRowDiffForEmptyPropertyTables() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+ $semanticData = new SemanticData( $subject );
+
+ $propertyTables = [];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( $propertyTables ) );
+
+ $instance = new PropertyTableRowDiffer(
+ $store,
+ $this->propertyTableRowMapper
+ );
+
+ $result = $instance->computeTableRowDiff(
+ 42,
+ $semanticData
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+ }
+
+ public function testChangeOp() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+ $semanticData = new SemanticData( $subject );
+
+ $propertyTables = [];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( $propertyTables ) );
+
+ $instance = new PropertyTableRowDiffer(
+ $store,
+ $this->propertyTableRowMapper
+ );
+
+ $instance->setChangeOp( new ChangeOp( $subject ) );
+
+ $result = $instance->computeTableRowDiff(
+ 42,
+ $semanticData
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\ChangeOp\ChangeOp',
+ $instance->getChangeOp()
+ );
+ }
+
+ public function testChangeOpWithUnknownFixedProperty() {
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'getFixedProperty' )
+ ->will( $this->returnValue( '_UNKNOWN_FIXED_PROPERTY' ) );
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+ $semanticData = new SemanticData( $subject );
+
+ $propertyTables = [ $propertyTable ];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( $propertyTables ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( $propertyTables ) );
+
+ $instance = new PropertyTableRowDiffer(
+ $store,
+ $this->propertyTableRowMapper
+ );
+
+ $instance->setChangeOp( new ChangeOp( $subject ) );
+
+ $result = $instance->computeTableRowDiff(
+ 42,
+ $semanticData
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\ChangeOp\ChangeOp',
+ $instance->getChangeOp()
+ );
+
+ $this->assertEmpty(
+ $instance->getChangeOp()->getFixedPropertyRecords()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowMapperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowMapperTest.php
new file mode 100644
index 00000000..fe5cb91b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableRowMapperTest.php
@@ -0,0 +1,206 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\SQLStore\PropertyTableRowMapper;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableRowMapper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PropertyTableRowMapperTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyTableRowMapper',
+ new PropertyTableRowMapper( $store )
+ );
+ }
+
+ public function testMapToRowsOnEmptyTable() {
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+ $semanticData = new SemanticData( $subject );
+
+ $propertyTables = [];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( $propertyTables ) );
+
+ $instance = new PropertyTableRowMapper(
+ $store
+ );
+
+ $result = $instance->mapToRows(
+ 42,
+ $semanticData
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $result
+ );
+ }
+
+ public function testMapToRowsWithFixedProperty() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'makeSMWPropertyID', 'makeSMWPageID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->once() )
+ ->method( 'makeSMWPropertyID' )
+ ->will( $this->returnValue( 9999 ) );
+
+ $idTable->expects( $this->once() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 1001 ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $semanticData = new SemanticData( $subject );
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( 'Foo_test_123'),
+ new DIWikiPage( 'Bar', NS_MAIN )
+ );
+
+ $propertyTables = [ 'smw_foo' => $propertyTable ];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getPropertyTables', 'findPropertyTableID', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->once() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( 'smw_foo' ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( $propertyTables ) );
+
+ $instance = new PropertyTableRowMapper(
+ $store
+ );
+
+ list( $rows, $textItems, $propertyList, $fixedPropertyList ) = $instance->mapToRows(
+ 42,
+ $semanticData
+ );
+
+ $this->assertArrayHasKey(
+ 'Foo_test_123',
+ $propertyList
+ );
+
+ $this->assertArrayHasKey(
+ 'smw_foo',
+ $fixedPropertyList
+ );
+ }
+
+ public function testNewChangeOp() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'makeSMWPropertyID', 'makeSMWPageID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->once() )
+ ->method( 'makeSMWPropertyID' )
+ ->will( $this->returnValue( 9999 ) );
+
+ $idTable->expects( $this->once() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 1001 ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( true ) );
+
+ $subject = new DIWikiPage( 'Foo', NS_MAIN );
+
+ $semanticData = new SemanticData( $subject );
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( 'Foo_test_123'),
+ new DIWikiPage( 'Bar', NS_MAIN )
+ );
+
+ $propertyTables = [ 'smw_foo' => $propertyTable ];
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->setMethods( [ 'getPropertyTables', 'findPropertyTableID', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->once() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( 'smw_foo' ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( $propertyTables ) );
+
+ $instance = new PropertyTableRowMapper(
+ $store
+ );
+
+ $changeOp = $instance->newChangeOp(
+ 42,
+ $semanticData
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\ChangeOp\ChangeOp',
+ $changeOp
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableUpdaterTest.php
new file mode 100644
index 00000000..04da2e66
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/PropertyTableUpdaterTest.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\PropertyTableUpdater;
+use SMW\Parameters;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\PropertyTableUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class PropertyTableUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $idTable;
+ private $connection;
+ private $propertyTable;
+ private $propertyStatisticsStore;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->idTable = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $this->idTable ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $this->propertyTable = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PropertyTableUpdater::class,
+ new PropertyTableUpdater( $this->store, $this->propertyStatisticsStore )
+ );
+ }
+
+ public function testUpdate_OnEmptyInsertRows() {
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->propertyStatisticsStore->expects( $this->once() )
+ ->method( 'addToUsageCounts' );
+
+ $instance = new PropertyTableUpdater(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $params= new Parameters(
+ [
+ 'insert_rows' => [],
+ 'delete_rows' => [],
+ 'new_hashes' => []
+ ]
+ );
+
+ $instance->update( 42, $params );
+ }
+
+ public function testUpdate_WithInsertRows() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'insert' );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'delete' );
+
+ $this->idTable->expects( $this->once() )
+ ->method( 'setPropertyTableHashes' );
+
+ $this->propertyTable->expects( $this->any() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'table_foo' => $this->propertyTable ] ) );
+
+ $this->propertyStatisticsStore->expects( $this->once() )
+ ->method( 'addToUsageCounts' )
+ ->with( $this->equalTo( [ 99998 => -1, 99999 => 1 ] ) );
+
+ $instance = new PropertyTableUpdater(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $params = new Parameters(
+ [
+ 'insert_rows' => [
+ 'table_foo' => [
+ [ 's_id' => 1001, 'p_id' => 99999 ]
+ ]
+ ],
+ 'delete_rows' => [
+ 'table_foo' => [
+ [ 's_id' => 1001, 'p_id' => 99998 ]
+ ]
+ ],
+ 'new_hashes' => []
+ ]
+ );
+
+ $instance->update( 42, $params );
+ }
+
+ public function testUpdate_WithInsertRowsButMissingIdFieldThrowsException() {
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'table_foo' => $this->propertyTable ] ) );
+
+ $instance = new PropertyTableUpdater(
+ $this->store,
+ $this->propertyStatisticsStore
+ );
+
+ $params= new Parameters(
+ [
+ 'insert_rows' => [
+ 'table_foo' => []
+ ],
+ 'delete_rows' => [
+ 'table_foo' => []
+ ],
+ 'new_hashes' => []
+ ]
+ );
+
+ $this->setExpectedException( '\SMW\SQLStore\Exception\TableMissingIdFieldException' );
+ $instance->update( 42, $params );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksTableUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksTableUpdaterTest.php
new file mode 100644
index 00000000..817b3330
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksTableUpdaterTest.php
@@ -0,0 +1,215 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryDependency;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DependencyLinksTableUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $spyLogger;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyLogger = $this->testEnvironment->newSpyLogger();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater',
+ new DependencyLinksTableUpdater( $this->store )
+ );
+ }
+
+ public function testAddToUpdateList() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getId' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getId' )
+ ->will( $this->onConsecutiveCalls( 1001 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'delete' )
+ ->with(
+ $this->equalTo( \SMWSQLStore3::QUERY_LINKS_TABLE ),
+ $this->equalTo( [ 's_id' => 42 ] ) );
+
+ $insert[] = [
+ 's_id' => 42,
+ 'o_id' => 1001
+ ];
+
+ $connection->expects( $this->once() )
+ ->method( 'insert' )
+ ->with(
+ $this->equalTo( \SMWSQLStore3::QUERY_LINKS_TABLE ),
+ $this->equalTo( $insert ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->setConnectionManager( $connectionManager );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $instance = new DependencyLinksTableUpdater(
+ $store
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->clear();
+
+ $instance->addToUpdateList( 42, [ DIWikiPage::newFromText( 'Bar' ) ] );
+ $instance->doUpdate();
+ }
+
+ public function testAddToUpdateListOnNull_List() {
+
+ $instance = new DependencyLinksTableUpdater(
+ $this->store
+ );
+
+ $this->assertNull(
+ $instance->addToUpdateList( 42, null )
+ );
+ }
+
+ public function testAddToUpdateListOnZero_Id() {
+
+ $instance = new DependencyLinksTableUpdater(
+ $this->store
+ );
+
+ $this->assertNull(
+ $instance->addToUpdateList( 0, [] )
+ );
+ }
+
+ public function testAddToUpdateListOnEmpty_List() {
+
+ $instance = new DependencyLinksTableUpdater(
+ $this->store
+ );
+
+ $this->assertNull(
+ $instance->addToUpdateList( 42, [] )
+ );
+ }
+
+ public function testAddDependenciesFromQueryResultWhereObjectIdIsYetUnknownWhichRequiresToCreateTheIdOnTheFly() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getId', 'makeSMWPageID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getId' )
+ ->will( $this->returnValue( 0 ) );
+
+ $idTable->expects( $this->any() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 1001 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'delete' )
+ ->with(
+ $this->equalTo( \SMWSQLStore3::QUERY_LINKS_TABLE ),
+ $this->equalTo( [ 's_id' => 42 ] ) );
+
+ $insert[] = [
+ 's_id' => 42,
+ 'o_id' => 1001
+ ];
+
+ $connection->expects( $this->once() )
+ ->method( 'insert' )
+ ->with(
+ $this->equalTo( \SMWSQLStore3::QUERY_LINKS_TABLE ),
+ $this->equalTo( $insert ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->setConnectionManager( $connectionManager );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $instance = new DependencyLinksTableUpdater(
+ $store
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->clear();
+
+ $instance->addToUpdateList( 42, [ DIWikiPage::newFromText( 'Bar', SMW_NS_PROPERTY ) ] );
+ $instance->doUpdate();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksUpdateJournalTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksUpdateJournalTest.php
new file mode 100644
index 00000000..48db006a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/DependencyLinksUpdateJournalTest.php
@@ -0,0 +1,204 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryDependency;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\QueryDependency\DependencyLinksUpdateJournal;
+use Title;
+
+/**
+ * @covers \SMW\SQLStore\QueryDependency\DependencyLinksUpdateJournal
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class DependencyLinksUpdateJournalTest extends \PHPUnit_Framework_TestCase {
+
+ private $cache;
+ private $callableUpdate;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->callableUpdate = $this->getMockBuilder( '\SMW\MediaWiki\Deferred\CallableUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $queryDependencyLinksStore = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryDependencyLinksStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ DependencyLinksUpdateJournal::class,
+ new DependencyLinksUpdateJournal( $this->cache, $this->callableUpdate )
+ );
+ }
+
+ public function testMakeKey() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+ $title = \Title::newFromText( 'Foo' );
+
+ $this->assertContains(
+ 'smw:update:qdep',
+ DependencyLinksUpdateJournal::makeKey( $subject )
+ );
+
+ $this->assertSame(
+ DependencyLinksUpdateJournal::makeKey( $title ),
+ DependencyLinksUpdateJournal::makeKey( $subject )
+ );
+ }
+
+ public function testUpdateFromList() {
+
+ $this->cache->expects( $this->atLeastOnce() )
+ ->method( 'save' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $hashList = [
+ 'Foo#0##'
+ ];
+
+ $instance->updateFromList( $hashList );
+ }
+
+ public function testUpdate() {
+
+ $this->cache->expects( $this->atLeastOnce() )
+ ->method( 'save' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $instance->update( DIWikiPage::newFromText( 'Foo' ) );
+ }
+
+ public function testUpdateFromTitle() {
+
+ $this->cache->expects( $this->atLeastOnce() )
+ ->method( 'save' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $instance->update( Title::newFromText( 'Foo' ) );
+ }
+
+ public function testHas() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $this->assertTrue(
+ $instance->has( DIWikiPage::newFromText( 'Foo' ) )
+ );
+ }
+
+ public function testHasOnDIWikiPageWithSubobject() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $this->assertTrue(
+ $instance->has( new DIWikiPage( 'Foo', NS_MAIN, '', 'Bar' ) )
+ );
+ }
+
+ public function testHasFromTitle() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'contains' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $this->assertTrue(
+ $instance->has( Title::newFromText( 'Foo' ) )
+ );
+ }
+
+ public function testDelete() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'delete' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) );
+
+ $this->callableUpdate->expects( $this->once() )
+ ->method( 'setCallback' )
+ ->will( $this->returnCallback( function( $callback ) {
+ return call_user_func( $callback );
+ } ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $instance->delete( DIWikiPage::newFromText( 'Foo' ) );
+ }
+
+ public function testDeleteFromTitle() {
+
+ $this->cache->expects( $this->once() )
+ ->method( 'delete' )
+ ->with( $this->stringContains( 'smw:update:qdep:7ab9f795d4ce7c20051947ede72baec3' ) );
+
+ $this->callableUpdate->expects( $this->once() )
+ ->method( 'setCallback' )
+ ->will( $this->returnCallback( function( $callback ) {
+ return call_user_func( $callback );
+ } ) );
+
+ $instance = new DependencyLinksUpdateJournal(
+ $this->cache,
+ $this->callableUpdate
+ );
+
+ $instance->delete( Title::newFromText( 'Foo' ) );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/EntityIdListRelevanceDetectionFilterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/EntityIdListRelevanceDetectionFilterTest.php
new file mode 100644
index 00000000..ef90f454
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/EntityIdListRelevanceDetectionFilterTest.php
@@ -0,0 +1,253 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryDependency;
+
+use SMW\DIWikiPage;
+use SMW\SQLStore\QueryDependency\EntityIdListRelevanceDetectionFilter;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryDependency\EntityIdListRelevanceDetectionFilter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class EntityIdListRelevanceDetectionFilterTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $spyLogger;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyLogger = $this->testEnvironment->newSpyLogger();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ EntityIdListRelevanceDetectionFilter::class,
+ new EntityIdListRelevanceDetectionFilter( $store, $changeOp )
+ );
+ }
+
+ public function testgetFilteredIdListOnExemptedPredefinedProperty() {
+
+ $orderedDiffByTable = [
+ 'fpt_mdat' => [
+ 'property' => [
+ 'key' => '_MDAT',
+ 'p_id' => 29
+ ],
+ 'insert' => [
+ [
+ 's_id' => 201,
+ 'o_serialized' => '1/2016/6/1/11/1/48/0',
+ 'o_sortkey' => '2457540.9595833'
+ ]
+ ],
+ 'delete' => [
+ [
+ 's_id' => 202,
+ 'o_serialized' => '1/2016/6/1/11/1/59/0',
+ 'o_sortkey' => '2457540.9582292'
+ ]
+ ]
+ ]
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getChangedEntityIdSummaryList', 'getOrderedDiffByTable' ] )
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [ 29, 201, 202, 1001 ] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getOrderedDiffByTable' )
+ ->will( $this->returnValue( $orderedDiffByTable ) );
+
+ $instance = new EntityIdListRelevanceDetectionFilter(
+ $store,
+ $changeOp
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setPropertyExemptionList(
+ [ '_MDAT' ]
+ );
+
+ $this->assertEquals(
+ [ 1001 ],
+ $instance->getFilteredIdList()
+ );
+ }
+
+ public function testgetFilteredIdListOnAffiliatePredefinedProperty() {
+
+ $orderedDiffByTable = [
+ 'fpt_dat' => [
+ 'property' => [
+ 'key' => '_MDAT',
+ 'p_id' => 29
+ ],
+ 'insert' => [
+ [
+ 's_id' => 201,
+ 'o_serialized' => '1/2016/6/1/11/1/48/0',
+ 'o_sortkey' => '2457540.9595833'
+ ]
+ ],
+ 'delete' => [
+ [
+ 's_id' => 202,
+ 'o_serialized' => '1/2016/6/1/11/1/59/0',
+ 'o_sortkey' => '2457540.9582292'
+ ]
+ ]
+ ]
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getChangedEntityIdSummaryList', 'getOrderedDiffByTable' ] )
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [ 1001 ] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getOrderedDiffByTable' )
+ ->will( $this->returnValue( $orderedDiffByTable ) );
+
+ $instance = new EntityIdListRelevanceDetectionFilter(
+ $store,
+ $changeOp
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setAffiliatePropertyDetectionList(
+ [ '_MDAT' ]
+ );
+
+ $this->assertEquals(
+ [ 1001, 201, 202 ],
+ $instance->getFilteredIdList()
+ );
+ }
+
+ public function testgetFilteredIdListOnExemptedUserdefinedProperty() {
+
+ $orderedDiffByTable = [
+ 'fpt_foo' => [
+ 'insert' => [
+ [
+ 'p_id' => 100,
+ 's_id' => 201,
+ 'o_serialized' => '1/2016/6/1/11/1/48/0',
+ 'o_sortkey' => '2457540.9595833'
+ ]
+ ],
+ 'delete' => [
+ [
+ 'p_id' => 100,
+ 's_id' => 201,
+ 'o_serialized' => '1/2016/6/1/11/1/59/0',
+ 'o_sortkey' => '2457540.9582292'
+ ]
+ ]
+ ]
+ ];
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getDataItemById' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getDataItemById' )
+ ->with( $this->equalTo( 100 ) )
+ ->will( $this->returnValue( DIWikiPage::newFromText( 'Has date', SMW_NS_PROPERTY ) ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getChangedEntityIdSummaryList', 'getOrderedDiffByTable' ] )
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [ 100, 201, 1001 ] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getOrderedDiffByTable' )
+ ->will( $this->returnValue( $orderedDiffByTable ) );
+
+ $instance = new EntityIdListRelevanceDetectionFilter(
+ $store,
+ $changeOp
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setPropertyExemptionList(
+ [ 'Has date' ]
+ );
+
+ $this->assertEquals(
+ [ 1001 ],
+ $instance->getFilteredIdList()
+ );
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryDependencyLinksStoreTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryDependencyLinksStoreTest.php
new file mode 100644
index 00000000..6b168261
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryDependencyLinksStoreTest.php
@@ -0,0 +1,1034 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryDependency;
+
+use SMW\DIWikiPage;
+use SMW\RequestOptions;
+use SMW\SQLStore\QueryDependency\QueryDependencyLinksStore;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryDependency\QueryDependencyLinksStore
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class QueryDependencyLinksStoreTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $spyLogger;
+ private $jobFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->spyLogger = $this->testEnvironment->newSpyLogger();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->store->setLogger(
+ $this->spyLogger
+ );
+
+ $namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $namespaceExaminer->expects( $this->any() )
+ ->method( 'isSemanticEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobFactory', $this->jobFactory );
+ $this->testEnvironment->registerObject( 'NamespaceExaminer', $namespaceExaminer );
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ $this->testEnvironment->clearPendingDeferredUpdates();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $this->store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\QueryDependencyLinksStore',
+ new QueryDependencyLinksStore( $queryResultDependencyListResolver, $dependencyLinksTableUpdater )
+ );
+ }
+
+ public function testPruneOutdatedTargetLinks() {
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( 'Foo' ) ) );
+
+ $changeOp->expects( $this->once() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $this->assertTrue(
+ $instance->pruneOutdatedTargetLinks( $changeOp )
+ );
+ }
+
+ public function testPruneOutdatedTargetLinksBeingDisabled() {
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setEnabled( false );
+
+ $this->assertNull(
+ $instance->pruneOutdatedTargetLinks( $changeOp )
+ );
+ }
+
+ public function testParserCachePurgeJobParametersOnBlacklistedProperty() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $entityIdListRelevanceDetectionFilter = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\EntityIdListRelevanceDetectionFilter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityIdListRelevanceDetectionFilter->expects( $this->once() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $entityIdListRelevanceDetectionFilter->expects( $this->once() )
+ ->method( 'getFilteredIdList' )
+ ->will( $this->returnValue( [ 1 ] ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $expected = [
+ 'idlist' => [ 1 ],
+ 'exec.mode' => 'exec.journal'
+ ];
+
+ $nullJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\NullJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->once() )
+ ->method( 'newParserCachePurgeJob' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( $expected ) )
+ ->will( $this->returnValue( $nullJob ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->pushParserCachePurgeJob( $entityIdListRelevanceDetectionFilter );
+ }
+
+ public function testParserCachePurgeJobParametersBeingDisabled() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $entityIdListRelevanceDetectionFilter = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\EntityIdListRelevanceDetectionFilter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->never() )
+ ->method( 'newParserCachePurgeJob' );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setEnabled( false );
+
+ $instance->pushParserCachePurgeJob( $entityIdListRelevanceDetectionFilter );
+ }
+
+ public function testParserCachePurgeJobParametersOnEmptyList() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $entityIdListRelevanceDetectionFilter = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\EntityIdListRelevanceDetectionFilter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityIdListRelevanceDetectionFilter->expects( $this->once() )
+ ->method( 'getFilteredIdList' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->never() )
+ ->method( 'newParserCachePurgeJob' );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setEnabled( true );
+
+ $instance->pushParserCachePurgeJob( $entityIdListRelevanceDetectionFilter );
+ }
+
+ public function testFindEmbeddedQueryTargetLinksHashListFrom() {
+
+ $row = new \stdClass;
+ $row->s_id = 1001;
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getDataItemPoolHashListFor' ] )
+ ->getMock();
+
+ $idTable->expects( $this->once() )
+ ->method( 'getDataItemPoolHashListFor' );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'select' )
+ ->with(
+ $this->equalTo( \SMWSQLStore3::QUERY_LINKS_TABLE ),
+ $this->anything(),
+ $this->equalTo( [ 'o_id' => [ 42 ] ] ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->setConnectionManager( $connectionManager );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $requestOptions = new RequestOptions();
+ $requestOptions->setLimit( 1 );
+ $requestOptions->setOffset( 200 );
+
+ $instance->findDependencyTargetLinks( [ 42 ], $requestOptions );
+ }
+
+ public function testFindEmbeddedQueryTargetLinksHashListBySubject() {
+
+ $row = new \stdClass;
+ $row->s_id = 1001;
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getDataItemPoolHashListFor' ] )
+ ->getMock();
+
+ $idTable->expects( $this->once() )
+ ->method( 'getDataItemPoolHashListFor' );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'select' )
+ ->with(
+ $this->equalTo( \SMWSQLStore3::QUERY_LINKS_TABLE ),
+ $this->anything(),
+ $this->equalTo( [ 'o_id' => [ 42 ] ] ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->setConnectionManager( $connectionManager );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $dependencyLinksTableUpdater->expects( $this->once() )
+ ->method( 'getId' )
+ ->will( $this->returnValue( 42 ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $requestOptions = new RequestOptions();
+ $requestOptions->setLimit( 1 );
+ $requestOptions->setOffset( 200 );
+
+ $instance->findDependencyTargetLinksForSubject( DIWikiPage::newFromText( 'Foo' ), $requestOptions );
+ }
+
+ public function testCountDependencies() {
+
+ $row = new \stdClass;
+ $row->count = 1001;
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->with(
+ $this->equalTo( \SMWSQLStore3::QUERY_LINKS_TABLE ),
+ $this->anything(),
+ $this->equalTo( [ 'o_id' => [ 42 ] ] ) )
+ ->will( $this->returnValue( $row ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->countDependencies( 42 );
+ }
+
+ public function testTryDoUpdateDependenciesByWhileBeingDisabled() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver->expects( $this->never() )
+ ->method( 'getDependencyListByLateRetrievalFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver->expects( $this->never() )
+ ->method( 'getDependencyListFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setEnabled( false );
+ $queryResult = '';
+
+ $instance->updateDependencies( $queryResult );
+ }
+
+ public function testUpdateDependencies_ExcludedRequestAction() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver->expects( $this->never() )
+ ->method( 'getDependencyListByLateRetrievalFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver->expects( $this->never() )
+ ->method( 'getDependencyListFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setEnabled( true );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->once() )
+ ->method( 'getOption' )
+ ->with( $this->equalTo( 'request.action' ) )
+ ->will( $this->returnValue( 'parse' ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $this->assertNull(
+ $instance->updateDependencies( $queryResult )
+ );
+ }
+
+ public function testTryDoUpdateDependenciesByForWhenDependencyListReturnsEmpty() {
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getId' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getId' )
+ ->will( $this->onConsecutiveCalls( 42, 1001 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds' ] )
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver->expects( $this->any() )
+ ->method( 'getDependencyListByLateRetrievalFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver->expects( $this->once() )
+ ->method( 'getDependencyListFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $instance->setEnabled( true );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 1 ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $instance->updateDependencies( $queryResult );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testDisabledDependenciesUpdateOnNotSupportedNamespace() {
+
+ $namespaceExaminer = $this->getMockBuilder( '\SMW\NamespaceExaminer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $namespaceExaminer->expects( $this->once() )
+ ->method( 'isSemanticEnabled' )
+ ->will( $this->returnValue( false ) );
+
+ $this->testEnvironment->registerObject( 'NamespaceExaminer', $namespaceExaminer );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver->expects( $this->never() )
+ ->method( 'getDependencyListByLateRetrievalFrom' );
+
+ $queryResultDependencyListResolver->expects( $this->never() )
+ ->method( 'getDependencyListFrom' );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setEnabled( true );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $instance->updateDependencies( $queryResult );
+ }
+
+ public function testdoUpdateDependenciesByFromQueryResult() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getTouched' )
+ ->will( $this->returnValue( 10 ) );
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $subject->expects( $this->any() )
+ ->method( 'getHash' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyValues' ] )
+ ->getMock();
+
+ $store->setConnectionManager( $connectionManager );
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver->expects( $this->any() )
+ ->method( 'getDependencyListByLateRetrievalFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver->expects( $this->any() )
+ ->method( 'getDependencyListFrom' )
+ ->will( $this->returnValue( [ null, DIWikiPage::newFromText( __METHOD__ ) ] ) );
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getId' )
+ ->will( $this->onConsecutiveCalls( 42, 1001 ) );
+
+ $dependencyLinksTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'addToUpdateList' )
+ ->with(
+ $this->equalTo( 1001 ),
+ $this->anything() );
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( $subject ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 1 ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $instance->updateDependencies( $queryResult );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ public function testdoUpdateDependenciesByFromQueryResultWhereObjectIdIsYetUnknownWhichRequiresToCreateTheIdOnTheFly() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver->expects( $this->any() )
+ ->method( 'getDependencyListByLateRetrievalFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResultDependencyListResolver->expects( $this->any() )
+ ->method( 'getDependencyListFrom' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromText( 'Foo', NS_CATEGORY ) ] ) );
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getId' )
+ ->will( $this->onConsecutiveCalls( 0, 0 ) );
+
+ $dependencyLinksTableUpdater->expects( $this->once() )
+ ->method( 'createId' )
+ ->will( $this->returnValue( 1001 ) );
+
+ $dependencyLinksTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'addToUpdateList' )
+ ->with(
+ $this->equalTo( 1001 ),
+ $this->anything() );
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( DIWikiPage::newFromText( __METHOD__ ) ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 1 ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $instance->updateDependencies( $queryResult );
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ /**
+ * @dataProvider titleProvider
+ */
+ public function testTryDoUpdateDependenciesByWithinSkewedTime( $title ) {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subject->expects( $this->atLeastOnce() )
+ ->method( 'getHash' )
+ ->will( $this->returnValue( 'Foo###' ) );
+
+ $subject->expects( $this->once() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $title ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->setConnectionManager( $connectionManager );
+
+ $queryResultDependencyListResolver = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResultDependencyListResolver->expects( $this->any() )
+ ->method( 'getDependencyListByLateRetrievalFrom' )
+ ->will( $this->returnValue( [] ) );
+
+ $dependencyLinksTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\DependencyLinksTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getId' )
+ ->will( $this->returnValue( 4 ) );
+
+ $dependencyLinksTableUpdater->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $instance = new QueryDependencyLinksStore(
+ $queryResultDependencyListResolver,
+ $dependencyLinksTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->spyLogger
+ );
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->any() )
+ ->method( 'getContextPage' )
+ ->will( $this->returnValue( $subject ) );
+
+ $query->expects( $this->any() )
+ ->method( 'getLimit' )
+ ->will( $this->returnValue( 1 ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $instance->updateDependencies( $queryResult );
+ }
+
+ public function titleProvider() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->once() )
+ ->method( 'getTouched' )
+ ->will( $this->returnValue( wfTimestamp( TS_MW ) + 60 ) );
+
+ $provider[] = [
+ $title
+ ];
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // This should be a `once` but it failed on PHP: hhvm-3.18 DB=sqlite; MW=master; PHPUNIT=5.7.*
+ // with "Method was expected to be called 1 times, actually called 0 times."
+ $title->expects( $this->any() )
+ ->method( 'getTouched' )
+ ->will( $this->returnValue( '2017-06-15 08:36:55+00' ) );
+
+ $provider[] = [
+ $title
+ ];
+
+ $provider[] = [
+ null
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryReferenceBacklinksTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryReferenceBacklinksTest.php
new file mode 100644
index 00000000..14cb6838
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryReferenceBacklinksTest.php
@@ -0,0 +1,134 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryDependency;
+
+use SMW\DataItemFactory;
+use SMW\RequestOptions;
+use SMW\SQLStore\QueryDependency\QueryReferenceBacklinks;
+
+/**
+ * @covers \SMW\SQLStore\QueryDependency\QueryReferenceBacklinks
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QueryReferenceBacklinksTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $queryDependencyLinksStore = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryDependencyLinksStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\QueryReferenceBacklinks',
+ new QueryReferenceBacklinks( $queryDependencyLinksStore )
+ );
+ }
+
+ public function testAddQueryReferenceBacklinksTo() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN, '', 'foobar' );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $subject ) );
+
+ $semanticData->expects( $this->any() )
+ ->method( 'addPropertyObjectValue' )
+ ->with(
+ $this->equalTo( $this->dataItemFactory->newDIProperty( '_ASK' ) ),
+ $this->equalTo( $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN ) ) );
+
+ $queryDependencyLinksStore = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryDependencyLinksStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryDependencyLinksStore->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $queryDependencyLinksStore->expects( $this->any() )
+ ->method( 'findEmbeddedQueryIdListBySubject' )
+ ->with( $this->equalTo( $subject ) )
+ ->will( $this->returnValue( [ 'Foo#0##' => 42 ] ) );
+
+ $queryDependencyLinksStore->expects( $this->once() )
+ ->method( 'findDependencyTargetLinksForSubject' )
+ ->will( $this->returnValue( [ 'Foo#0##' ] ) );
+
+ $instance = new QueryReferenceBacklinks(
+ $queryDependencyLinksStore
+ );
+
+ $requestOptions = new RequestOptions();
+
+ $this->assertTrue(
+ $instance->addReferenceLinksTo( $semanticData, $requestOptions )
+ );
+ }
+
+ public function testFindQueryReferenceBacklinks() {
+
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN, '', '' );
+
+ $queryDependencyLinksStore = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryDependencyLinksStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryDependencyLinksStore->expects( $this->any() )
+ ->method( 'findDependencyTargetLinksForSubject' )
+ ->will( $this->returnValue( [ 'Foo#0##' ] ) );
+
+ $instance = new QueryReferenceBacklinks(
+ $queryDependencyLinksStore
+ );
+
+ $requestOptions = new RequestOptions();
+
+ $this->assertEquals(
+ [ 'Foo#0##' ],
+ $instance->findReferenceLinks( $subject, $requestOptions )
+ );
+ }
+
+ public function testInspectFurtherLinkRequirement() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_ASK' );
+ $subject = $this->dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN, '', '' );
+
+ $queryDependencyLinksStore = $this->getMockBuilder( '\SMW\SQLStore\QueryDependency\QueryDependencyLinksStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryReferenceBacklinks(
+ $queryDependencyLinksStore
+ );
+
+ $html = '';
+
+ $this->assertFalse(
+ $instance->doesRequireFurtherLink( $property, $subject, $html )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryResultDependencyListResolverTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryResultDependencyListResolverTest.php
new file mode 100644
index 00000000..b0638a0b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependency/QueryResultDependencyListResolverTest.php
@@ -0,0 +1,602 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryDependency;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\ConceptDescription;
+use SMW\Query\Language\Conjunction;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\Query\Language\SomeProperty;
+use SMW\Query\Language\ValueDescription;
+use SMW\Query\PrintRequest;
+use SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver;
+use SMW\Tests\TestEnvironment;
+use SMWDIBlob as DIBlob;
+use SMWQuery as Query;
+
+/**
+ * @covers \SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class QueryResultDependencyListResolverTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $store;
+ private $hierarchyLookup;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'Store', $this->store );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver',
+ new QueryResultDependencyListResolver( $this->hierarchyLookup )
+ );
+ }
+
+ public function testTryTogetDependencyListFromForNonSetQueryResult() {
+
+ $instance = new QueryResultDependencyListResolver(
+ $this->hierarchyLookup
+ );
+
+ $this->assertEmpty(
+ $instance->getDependencyListFrom( '' )
+ );
+ }
+
+ public function testTryTogetDependencyListFromForLimitZeroQuery() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $query->setUnboundLimit( 0 );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $queryResult->expects( $this->never() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $this->store ) );
+
+ $this->hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->hierarchyLookup->expects( $this->any() )
+ ->method( 'getConsecutiveHierarchyList' )
+ ->will( $this->returnValue( [] ) );
+
+ $instance = new QueryResultDependencyListResolver(
+ $this->hierarchyLookup
+ );
+
+ $this->assertEmpty(
+ $instance->getDependencyListFrom( $queryResult )
+ );
+ }
+
+ public function testExcludePropertyFromDependencyDetection() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $this->store ) );
+
+ $this->hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->hierarchyLookup->expects( $this->any() )
+ ->method( 'hasSubproperty' )
+ ->will( $this->returnValue( true ) );
+
+ $this->hierarchyLookup->expects( $this->at( 1 ) )
+ ->method( 'getConsecutiveHierarchyList' )
+ ->with( $this->equalTo( new DIProperty( 'Foobar' ) ) )
+ ->will( $this->returnValue(
+ [ new DIProperty( 'Subprop' ) ] ) );
+
+ $instance = new QueryResultDependencyListResolver(
+ $this->hierarchyLookup
+ );
+
+ $instance->setPropertyDependencyExemptionlist( [ 'Subprop' ] );
+
+ $expected = [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ // DIWikiPage::newFromText( 'Subprop', SMW_NS_PROPERTY ) removed
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getDependencyListFrom( $queryResult )
+ );
+ }
+
+
+ /**
+ * @dataProvider queryProvider
+ */
+ public function testgetDependencyListFrom( $query, $expected ) {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $this->store ) );
+
+ $this->hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryResultDependencyListResolver(
+ $this->hierarchyLookup
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getDependencyListFrom( $queryResult )
+ );
+ }
+
+ public function testgetDependencyListByLateRetrievalFrom() {
+
+ $subject = DIWikiPage::newFromText( 'Bar' );
+
+ $description = new ClassDescription(
+ DIWikiPage::newFromText( 'Foocat', NS_CATEGORY )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( DIWikiPage::newFromText( 'Foo' ) );
+
+ $resolverJournal = $this->getMockBuilder( '\SMW\Query\Result\ResolverJournal' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resolverJournal->expects( $this->once() )
+ ->method( 'getEntityList' )
+ ->will( $this->returnValue( [ $subject ] ) );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getResolverJournal' )
+ ->will( $this->returnValue( $resolverJournal ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $this->hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryResultDependencyListResolver(
+ $this->hierarchyLookup
+ );
+
+ $this->assertEquals(
+ [ $subject ],
+ $instance->getDependencyListByLateRetrievalFrom( $queryResult )
+ );
+ }
+
+ public function testResolvePropertyHierarchy() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $this->store ) );
+
+ $this->hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->hierarchyLookup->expects( $this->any() )
+ ->method( 'hasSubproperty' )
+ ->will( $this->returnValue( true ) );
+
+ $this->hierarchyLookup->expects( $this->at( 1 ) )
+ ->method( 'getConsecutiveHierarchyList' )
+ ->with( $this->equalTo( new DIProperty( 'Foobar' ) ) )
+ ->will( $this->returnValue(
+ [ new DIProperty( 'Subprop' ) ] ) );
+
+ $instance = new QueryResultDependencyListResolver(
+ $this->hierarchyLookup
+ );
+
+ $expected = [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ 'Subprop#102##' => DIWikiPage::newFromText( 'Subprop', SMW_NS_PROPERTY ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getDependencyListFrom( $queryResult )
+ );
+ }
+
+ public function testResolveCategoryHierarchy() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ $description = new ClassDescription(
+ DIWikiPage::newFromText( 'Foocat', NS_CATEGORY )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->once() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getQuery' )
+ ->will( $this->returnValue( $query ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $this->store ) );
+
+ $this->hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->hierarchyLookup->expects( $this->any() )
+ ->method( 'hasSubcategory' )
+ ->will( $this->returnValue( true ) );
+
+ $this->hierarchyLookup->expects( $this->at( 1 ) )
+ ->method( 'getConsecutiveHierarchyList' )
+ ->with( $this->equalTo( DIWikiPage::newFromText( 'Foocat', NS_CATEGORY ) ) )
+ ->will( $this->returnValue(
+ [
+ DIWikiPage::newFromText( 'Subcat', NS_CATEGORY ),
+ DIWikiPage::newFromText( 'Foocat', NS_CATEGORY ) ] ) );
+
+ $instance = new QueryResultDependencyListResolver(
+ $this->hierarchyLookup
+ );
+
+ $expected = [
+ DIWikiPage::newFromText( 'Foo' ),
+ 'Subcat#14##' => DIWikiPage::newFromText( 'Subcat', NS_CATEGORY ),
+ 'Foocat#14##' => DIWikiPage::newFromText( 'Foocat', NS_CATEGORY ),
+ DIWikiPage::newFromText( 'Foocat', NS_CATEGORY )
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getDependencyListFrom( $queryResult )
+ );
+ }
+
+ public function queryProvider() {
+
+ $subject = DIWikiPage::newFromText( 'Foo' );
+
+ #0
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ]
+ ];
+
+ #1
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( new DIBlob( 'Bar' ) )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ]
+ ];
+
+ #2 uses inverse property declaration
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar', true ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ]
+ ];
+
+ #3 Conjunction
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $query = new Query( new Conjunction( [
+ $description,
+ new NamespaceDescription( NS_MAIN )
+ ] ) );
+
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ]
+ ];
+
+ #4 Disjunction
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $query = new Query( new Disjunction( [
+ $description,
+ new NamespaceDescription( NS_MAIN )
+ ] ) );
+
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ]
+ ];
+
+ #5
+ $description = new ClassDescription(
+ DIWikiPage::newFromText( 'Foocat', NS_CATEGORY )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Foocat', NS_CATEGORY )
+ ]
+ ];
+
+ #6
+ $description = new ConceptDescription(
+ DIWikiPage::newFromText( 'FooConcept', SMW_NS_CONCEPT )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ 'FooConcept#108##' => DIWikiPage::newFromText( 'FooConcept', SMW_NS_CONCEPT )
+ ]
+ ];
+
+ #7 Printrequest
+ $pv = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Foobaz' );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar', true ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, '', $pv )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ DIWikiPage::newFromText( 'Foobaz', SMW_NS_PROPERTY ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY ),
+ ]
+ ];
+
+ #8 Inverse printrequest
+ $pv = DataValueFactory::getInstance()->newPropertyValueByLabel( 'Foobaz' );
+ $pv->setInverse( true );
+
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar', true ),
+ new ValueDescription( DIWikiPage::newFromText( 'Bar' ) )
+ );
+
+ $description->addPrintRequest(
+ new PrintRequest( PrintRequest::PRINT_PROP, '', $pv )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'Bar' ),
+ DIWikiPage::newFromText( 'Foobaz', SMW_NS_PROPERTY ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY ),
+ ]
+ ];
+
+ #9 SMW_CMP_EQ comparator
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( DIWikiPage::newFromText( 'EQ_Comparator' ), null, SMW_CMP_EQ )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ DIWikiPage::newFromText( 'EQ_Comparator' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ]
+ ];
+
+ #10 Ignore entity with SMW_CMP_EQ comparator
+ $description = new SomeProperty(
+ new DIProperty( 'Foobar' ),
+ new ValueDescription( DIWikiPage::newFromText( 'LIKE_Comparator' ), null, SMW_CMP_LIKE )
+ );
+
+ $query = new Query( $description );
+ $query->setContextPage( $subject );
+
+ $provider[] = [
+ $query,
+ [
+ DIWikiPage::newFromText( 'Foo' ),
+ 'Foobar#102##' => DIWikiPage::newFromText( 'Foobar', SMW_NS_PROPERTY )
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependencyLinksStoreFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependencyLinksStoreFactoryTest.php
new file mode 100644
index 00000000..7f38b995
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryDependencyLinksStoreFactoryTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\QueryDependencyLinksStoreFactory;
+
+/**
+ * @covers \SMW\SQLStore\QueryDependencyLinksStoreFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class QueryDependencyLinksStoreFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependencyLinksStoreFactory',
+ new QueryDependencyLinksStoreFactory()
+ );
+ }
+
+ public function testCanConstructQueryResultDependencyListResolver() {
+
+ $instance = new QueryDependencyLinksStoreFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\QueryResultDependencyListResolver',
+ $instance->newQueryResultDependencyListResolver()
+ );
+ }
+
+ public function testCanConstructQueryDependencyLinksStore() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new QueryDependencyLinksStoreFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\QueryDependencyLinksStore',
+ $instance->newQueryDependencyLinksStore( $store )
+ );
+ }
+
+ public function testCanConstructEntityIdListRelevanceDetectionFilter() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryDependencyLinksStoreFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\EntityIdListRelevanceDetectionFilter',
+ $instance->newEntityIdListRelevanceDetectionFilter( $store, $changeOp )
+ );
+ }
+
+ public function testCanConstructQueryReferenceBacklinks() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new QueryDependencyLinksStoreFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\QueryReferenceBacklinks',
+ $instance->newQueryReferenceBacklinks( $store )
+ );
+ }
+
+ public function testCanConstructDependencyLinksUpdateJournal() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new QueryDependencyLinksStoreFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryDependency\DependencyLinksUpdateJournal',
+ $instance->newDependencyLinksUpdateJournal()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/ConceptQuerySegmentBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/ConceptQuerySegmentBuilderTest.php
new file mode 100644
index 00000000..112a3a0c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/ConceptQuerySegmentBuilderTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\ConceptQuerySegmentBuilder;
+use Title;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\ConceptQuerySegmentBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ConceptQuerySegmentBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentListBuilder;
+ private $querySegmentListProcessor;
+ private $queryParser;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->querySegmentListProcessor = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListProcessor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->queryParser = $this->getMockBuilder( '\SMW\Query\Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\ConceptQuerySegmentBuilder',
+ new ConceptQuerySegmentBuilder( $this->querySegmentListBuilder, $this->querySegmentListProcessor )
+ );
+ }
+
+ public function testGetQuerySegmentFromOnNull() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->queryParser->expects( $this->any() )
+ ->method( 'getQueryDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $instance = new ConceptQuerySegmentBuilder(
+ $this->querySegmentListBuilder,
+ $this->querySegmentListProcessor
+ );
+
+ $instance->setQueryParser(
+ $this->queryParser
+ );
+
+ $this->assertNull(
+ $instance->getQuerySegmentFrom( '[[Foo]]' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php
new file mode 100644
index 00000000..d0852390
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreterFactoryTest.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\DescriptionInterpreterFactory;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreterFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DescriptionInterpreterFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreterFactory',
+ new DescriptionInterpreterFactory()
+ );
+ }
+
+ public function testCanConstructDispatchingDescriptionInterpreter() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new DescriptionInterpreterFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\DispatchingDescriptionInterpreter',
+ $instance->newDispatchingDescriptionInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php
new file mode 100644
index 00000000..5489db9f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreterTest.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DataItemFactory;
+use SMW\Query\DescriptionFactory;
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter;
+use SMW\SQLStore\QueryEngineFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ClassDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\ClassDescriptionInterpreter',
+ new ClassDescriptionInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testCompileDescription( $description, $pageId, $expected ) {
+
+ $objectIds = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPageID' ] )
+ ->getMock();
+
+ $objectIds->expects( $this->any() )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( $pageId ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIds ) );
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new ClassDescriptionInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $descriptionFactory = new DescriptionFactory();
+ $dataItemFactory = new DataItemFactory();
+
+ #0
+ $pageId = 42;
+
+ $description = $descriptionFactory->newClassDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->components = [ 1 => "t0.o_id" ];
+ $expected->joinfield = "t0.s_id";
+
+ $provider[] = [
+ $description,
+ $pageId,
+ $expected
+ ];
+
+ #1 Empty
+ $pageId = 0;
+
+ $description = $descriptionFactory->newClassDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', NS_CATEGORY )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 2;
+ $expected->components = [];
+ $expected->joinfield = "";
+
+ $provider[] = [
+ $description,
+ $pageId,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ComparatorMapperTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ComparatorMapperTest.php
new file mode 100644
index 00000000..e5f2c60b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ComparatorMapperTest.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\ComparatorMapper;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\ComparatorMapper
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ComparatorMapperTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\ComparatorMapper',
+ new ComparatorMapper()
+ );
+ }
+
+ public function testInvalidComparatorThrowsException() {
+
+ $value = '';
+
+ $valueDescription = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ComparatorMapper();
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->mapComparator( $valueDescription, $value );
+ }
+
+ /**
+ * @dataProvider comparatorProvider
+ */
+ public function testSQLComparatorElement( $comparator, $value, $expected ) {
+
+ $valueDescription = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $valueDescription->expects( $this->once() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( $comparator ) );
+
+ $instance = new ComparatorMapper();
+
+ $this->assertEquals(
+ $expected['comparator'],
+ $instance->mapComparator( $valueDescription, $value )
+ );
+
+ $this->assertEquals(
+ $expected['value'],
+ $value
+ );
+ }
+
+ public function comparatorProvider() {
+
+ $provider[] = [ SMW_CMP_EQ, 'Foo%_*?', [ 'comparator' => '=', 'value' => 'Foo%_*?' ] ];
+ $provider[] = [ SMW_CMP_LESS, 'Foo%_*?', [ 'comparator' => '<', 'value' => 'Foo%_*?' ] ];
+ $provider[] = [ SMW_CMP_GRTR, 'Foo%_*?', [ 'comparator' => '>', 'value' => 'Foo%_*?' ] ];
+ $provider[] = [ SMW_CMP_LEQ, 'Foo%_*?', [ 'comparator' => '<=', 'value' => 'Foo%_*?' ] ];
+ $provider[] = [ SMW_CMP_GEQ, 'Foo%_*?', [ 'comparator' => '>=', 'value' => 'Foo%_*?' ] ];
+ $provider[] = [ SMW_CMP_NEQ, 'Foo%_*?', [ 'comparator' => '!=', 'value' => 'Foo%_*?' ] ];
+
+ $provider[] = [ SMW_CMP_LIKE, 'Foo%_*?\\', [ 'comparator' => ' LIKE ', 'value' => 'Foo\%\_%_\\\\' ] ];
+ $provider[] = [ SMW_CMP_PRIM_LIKE, 'Foo%_*?\\', [ 'comparator' => ' LIKE ', 'value' => 'Foo\%\_%_\\\\' ] ];
+ $provider[] = [ SMW_CMP_NLKE, 'Foo%_*?\\', [ 'comparator' => ' NOT LIKE ', 'value' => 'Foo\%\_%_\\\\' ] ];
+ $provider[] = [ SMW_CMP_PRIM_NLKE, 'Foo%_*?\\', [ 'comparator' => ' NOT LIKE ', 'value' => 'Foo\%\_%_\\\\' ] ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php
new file mode 100644
index 00000000..d3058658
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ConceptDescriptionInterpreterTest.php
@@ -0,0 +1,241 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\ApplicationFactory;
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter;
+use SMW\SQLStore\QueryEngineFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ConceptDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentValidator;
+ private $descriptionInterpreterFactory;
+ private $queryParser;
+
+ private $descriptionFactory;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $applicationFactory = ApplicationFactory::getInstance();
+ $queryFactory = $applicationFactory->getQueryFactory();
+
+ $this->descriptionFactory = $queryFactory->newDescriptionFactory();
+ $this->queryParser = $queryFactory->newQueryParser();
+ $this->dataItemFactory = $applicationFactory->getDataItemFactory();
+
+ $this->descriptionInterpreterFactory = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\DescriptionInterpreterFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\ConceptDescriptionInterpreter',
+ new ConceptDescriptionInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+ public function testCheckForCircularReference() {
+
+ $circularReferenceGuard = $this->getMockBuilder( '\SMW\Utils\CircularReferenceGuard' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $circularReferenceGuard->expects( $this->once() )
+ ->method( 'isCircular' )
+ ->with( $this->equalTo( 'concept-42' ) )
+ ->will( $this->returnValue( true ) );
+
+ $objectIds = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPageID' ] )
+ ->getMock();
+
+ $objectIds->expects( $this->any() )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIds ) );
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $querySegmentListBuilder->expects( $this->any() )
+ ->method( 'getStore' )
+ ->will( $this->returnValue( $store ) );
+
+ $querySegmentListBuilder->expects( $this->any() )
+ ->method( 'getCircularReferenceGuard' )
+ ->will( $this->returnValue( $circularReferenceGuard ) );
+
+ $instance = new ConceptDescriptionInterpreter(
+ $querySegmentListBuilder
+ );
+
+ $description = $this->descriptionFactory->newConceptDescription(
+ $this->dataItemFactory->newDIWikiPage( 'Foo', SMW_NS_CONCEPT )
+ );
+
+ $instance->interpretDescription(
+ $description
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testInterpretDescription( $description, $concept, $expected ) {
+
+ $objectIds = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPageID' ] )
+ ->getMock();
+
+ $objectIds->expects( $this->any() )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( $concept ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIds ) );
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new ConceptDescriptionInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $instance->setQueryParser(
+ $this->queryParser
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $applicationFactory = ApplicationFactory::getInstance();
+
+ $descriptionFactory = $applicationFactory->getQueryFactory()->newDescriptionFactory();
+ $dataItemFactory = $applicationFactory->getDataItemFactory();
+
+ #0 No concept
+ $concept = false;
+
+ $description = $descriptionFactory->newConceptDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', SMW_NS_CONCEPT )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinfield = '';
+
+ $provider[] = [
+ $description,
+ $concept,
+ $expected
+ ];
+
+ #1 Cached concept
+ $concept = new \stdClass;
+ $concept->concept_size = 1;
+ $concept->concept_features = 1;
+ $concept->concept_depth = 1;
+ $concept->cache_date = strtotime( "now" );
+
+ $description = $descriptionFactory->newConceptDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', SMW_NS_CONCEPT )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinfield = 't0.s_id';
+ $expected->where = 't0.o_id=42';
+ $expected->queryNumber = 0;
+
+ $provider[] = [
+ $description,
+ $concept,
+ $expected
+ ];
+
+ #2 Non cached concept
+ $concept = new \stdClass;
+ $concept->concept_txt = "[[Category:Foo]]";
+ $concept->concept_size = 1;
+ $concept->concept_features = 1;
+ $concept->concept_depth = 1;
+ $concept->cache_date = false;
+
+ $description = $descriptionFactory->newConceptDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', SMW_NS_CONCEPT )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinfield = 't1.s_id';
+ $expected->components = [ 2 => 't1.o_id' ];
+ $expected->queryNumber = 1;
+
+ $provider[] = [
+ $description,
+ $concept,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/DisjunctionConjunctionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/DisjunctionConjunctionInterpreterTest.php
new file mode 100644
index 00000000..086f618d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/DisjunctionConjunctionInterpreterTest.php
@@ -0,0 +1,139 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\Query\DescriptionFactory;
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\DisjunctionConjunctionInterpreter;
+use SMW\SQLStore\QueryEngineFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\DisjunctionConjunctionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class DisjunctionConjunctionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentValidator;
+ private $descriptionFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\DisjunctionConjunctionInterpreter',
+ new DisjunctionConjunctionInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testInterpretDescription( $description, $expected ) {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new DisjunctionConjunctionInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $descriptionFactory = new DescriptionFactory();
+
+ #0 Disjunction
+ $description = $descriptionFactory->newDisjunction();
+
+ $description->addDescription(
+ $descriptionFactory->newNamespaceDescription( NS_HELP )
+ );
+
+ $description->addDescription(
+ $descriptionFactory->newNamespaceDescription( NS_MAIN )
+ );
+
+ $expectedDisjunction = new \stdClass;
+ $expectedDisjunction->type = 3;
+ $expectedDisjunction->components = [ 1 => true, 2 => true ];
+
+ $provider[] = [
+ $description,
+ $expectedDisjunction
+ ];
+
+ #1 Conjunction
+ $description = $descriptionFactory->newConjunction();
+
+ $description->addDescription(
+ $descriptionFactory->newNamespaceDescription( NS_HELP )
+ );
+
+ $description->addDescription(
+ $descriptionFactory->newNamespaceDescription( NS_MAIN )
+ );
+
+ $expectedConjunction = new \stdClass;
+ $expectedConjunction->type = 4;
+ $expectedConjunction->components = [ 1 => true, 2 => true ];
+
+ $provider[] = [
+ $description,
+ $expectedConjunction
+ ];
+
+ #2 No query
+ $description = $descriptionFactory->newConjunction();
+
+ $description->addDescription(
+ $descriptionFactory->newThingDescription()
+ );
+
+ $expectedConjunction = new \stdClass;
+ $expectedConjunction->type = 0;
+ $expectedConjunction->components = [];
+
+ $provider[] = [
+ $description,
+ $expectedConjunction
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php
new file mode 100644
index 00000000..2bcceb92
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/NamespaceDescriptionInterpreterTest.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\Query\DescriptionFactory;
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter;
+use SMW\SQLStore\QueryEngineFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class NamespaceDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentValidator;
+ private $descriptionFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionFactory = new DescriptionFactory();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\NamespaceDescriptionInterpreter',
+ new NamespaceDescriptionInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+ public function testInterpretDescription() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $description = $this->descriptionFactory->newNamespaceDescription(
+ NS_HELP
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->where = "t0.smw_namespace=";
+
+ $instance = new NamespaceDescriptionInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php
new file mode 100644
index 00000000..592265c1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/SomePropertyInterpreterTest.php
@@ -0,0 +1,511 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DataItemFactory;
+use SMW\Query\DescriptionFactory;
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\SomePropertyInterpreter;
+use SMW\SQLStore\QueryEngineFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\SomePropertyInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class SomePropertyInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentValidator;
+ private $descriptionFactory;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionFactory = new DescriptionFactory();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\SomePropertyInterpreter',
+ new SomePropertyInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+ public function testinterpretDescriptionForUnknownTablePropertyId() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( '' ) );
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' ),
+ $this->descriptionFactory->newThingDescription()
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 0;
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new SomePropertyInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ public function testinterpretDescriptionForNonIdSubject() {
+
+ $proptable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'usesIdSubject' ] )
+ ->getMock();
+
+ $proptable->expects( $this->any() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( false ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => $proptable ] ) );
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' ),
+ $this->descriptionFactory->newThingDescription()
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 0;
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new SomePropertyInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ public function testinterpretDescriptionForNonWikiPageTypeInverseProperty() {
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property->expects( $this->once() )
+ ->method( 'isInverse' )
+ ->will( $this->returnValue( true ) );
+
+ $property->expects( $this->once() )
+ ->method( 'findPropertyTypeID' )
+ ->will( $this->returnValue( '_txt' ) );
+
+ $proptable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'usesIdSubject' ] )
+ ->getMock();
+
+ $proptable->expects( $this->any() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => $proptable ] ) );
+
+ $description = $this->descriptionFactory->newSomeProperty(
+ $property,
+ $this->descriptionFactory->newThingDescription()
+ );
+ $expected = new \stdClass;
+ $expected->type = 0;
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new SomePropertyInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testinterpretDescription( $description, $isFixedPropertyTable, $indexField, $sortKeys, $expected ) {
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->any() )
+ ->method( 'getIndexField' )
+ ->will( $this->returnValue( $indexField ) );
+
+ $dataItemHandler->expects( $this->any() )
+ ->method( 'getTableFields' )
+ ->will( $this->returnValue( [ 'one', 'two' ] ) );
+
+ $dataItemHandler->expects( $this->any() )
+ ->method( 'getWhereConds' )
+ ->will( $this->returnValue( [ $indexField => 'fixedFooWhereCond' ] ) );
+
+ $objectIds = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPropertyID', 'getSMWPageID' ] )
+ ->getMock();
+
+ $objectIds->expects( $this->any() )
+ ->method( 'getSMWPropertyID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $objectIds->expects( $this->any() )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 91 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $proptable = $this->getMockBuilder( '\SMWSQLStore3Table' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $proptable->expects( $this->any() )
+ ->method( 'usesIdSubject' )
+ ->will( $this->returnValue( true ) );
+
+ $proptable->expects( $this->any() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( 'FooPropTable' ) );
+
+ $proptable->expects( $this->any() )
+ ->method( 'isFixedPropertyTable' )
+ ->will( $this->returnValue( $isFixedPropertyTable ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'findPropertyTableID' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ 'Foo' => $proptable ] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIds ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $querySegmentListBuilder = $queryEngineFactory->newQuerySegmentListBuilder();
+ $querySegmentListBuilder->setSortKeys( $sortKeys );
+
+ $instance = new SomePropertyInterpreter(
+ $querySegmentListBuilder
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $descriptionFactory = new DescriptionFactory();
+ $dataItemFactory = new DataItemFactory();
+
+ #0 Blob + wildcard
+ $isFixedPropertyTable = false;
+ $indexField = '';
+ $sortKeys = [];
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = $descriptionFactory->newSomeProperty(
+ $property,
+ $descriptionFactory->newThingDescription()
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinTable = 'FooPropTable';
+ $expected->components = [ 1 => "t0.p_id" ];
+ $expected->sortfields = [];
+
+ $provider[] = [
+ $description,
+ $isFixedPropertyTable,
+ $indexField,
+ $sortKeys,
+ $expected
+ ];
+
+ #1 WikiPage + SMW_CMP_EQ
+ $isFixedPropertyTable = false;
+ $indexField = 'wikipageIndex';
+ $sortKeys = [];
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = $descriptionFactory->newSomeProperty(
+ $property,
+ $descriptionFactory->newValueDescription( $dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN ), null, SMW_CMP_EQ )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinTable = 'FooPropTable';
+ $expected->components = [ 1 => "t0.p_id", 2 => "t0.wikipageIndex" ];
+ $expected->queryNumber = 0;
+ $expected->where = '';
+ $expected->sortfields = [];
+
+ $provider[] = [
+ $description,
+ $isFixedPropertyTable,
+ $indexField,
+ $sortKeys,
+ $expected
+ ];
+
+ #2 WikiPage + SMW_CMP_EQ + sort
+ $isFixedPropertyTable = false;
+ $indexField = 'wikipageIndex';
+ $sortKeys = [ 'Foo' => 'DESC' ];
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_wpg' );
+
+ $description = $descriptionFactory->newSomeProperty(
+ $property,
+ $descriptionFactory->newValueDescription( $dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN ), null, SMW_CMP_EQ )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinTable = 'FooPropTable';
+ $expected->components = [ 1 => "t0.p_id", 2 => "t0.wikipageIndex" ];
+ $expected->queryNumber = 0;
+ $expected->where = '';
+ $expected->sortfields = [ 'Foo' => 'idst0.smw_sort' ];
+ $expected->from = ' INNER JOIN AS idst0 ON idst0.smw_id=t0.wikipageIndex';
+
+ $provider[] = [
+ $description,
+ $isFixedPropertyTable,
+ $indexField,
+ $sortKeys,
+ $expected
+ ];
+
+ #3 Blob + SMW_CMP_EQ
+ $isFixedPropertyTable = false;
+ $indexField = 'blobIndex';
+ $sortKeys = [];
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = $descriptionFactory->newSomeProperty(
+ $property,
+ $descriptionFactory->newValueDescription( $dataItemFactory->newDIBlob( 'Bar' ), null, SMW_CMP_EQ )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinTable = 'FooPropTable';
+ $expected->components = [ 1 => "t0.p_id" ];
+ $expected->queryNumber = 0;
+ $expected->where = '(t0.blobIndex=fixedFooWhereCond)';
+ $expected->sortfields = [];
+
+ $provider[] = [
+ $description,
+ $isFixedPropertyTable,
+ $indexField,
+ $sortKeys,
+ $expected
+ ];
+
+ #4 Blob + SMW_CMP_EQ + sort
+ $isFixedPropertyTable = false;
+ $indexField = 'blobIndex';
+ $sortKeys = [ 'Foo' => 'ASC' ];
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = $descriptionFactory->newSomeProperty(
+ $property,
+ $descriptionFactory->newValueDescription( $dataItemFactory->newDIBlob( 'Bar' ), null, SMW_CMP_EQ )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinTable = 'FooPropTable';
+ $expected->components = [ 1 => "t0.p_id" ];
+ $expected->queryNumber = 0;
+ $expected->where = '(t0.blobIndex=fixedFooWhereCond)';
+ $expected->sortfields = [ 'Foo' => 't0.blobIndex' ];
+ $expected->from = '';
+
+ $provider[] = [
+ $description,
+ $isFixedPropertyTable,
+ $indexField,
+ $sortKeys,
+ $expected
+ ];
+
+ #5 Check SemanticMaps compatibility mode (invokes `getSQLCondition`)
+ $isFixedPropertyTable = false;
+ $indexField = 'blobIndex';
+ $sortKeys = [];
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $valueDescription = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getSQLCondition', 'getDataItem' ] )
+ ->getMock();
+
+ $valueDescription->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItemFactory->newDIBlob( '13,56' ) ) );
+
+ $valueDescription->expects( $this->once() )
+ ->method( 'getSQLCondition' )
+ ->will( $this->returnValue( 'foo AND bar' ) );
+
+ $description = $descriptionFactory->newSomeProperty(
+ $property,
+ $valueDescription
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinTable = 'FooPropTable';
+ $expected->components = [ 1 => "t0.p_id" ];
+ $expected->queryNumber = 0;
+ $expected->where = '(foo AND bar)';
+ $expected->sortfields = [];
+ $expected->from = '';
+
+ $provider[] = [
+ $description,
+ $isFixedPropertyTable,
+ $indexField,
+ $sortKeys,
+ $expected
+ ];
+
+ #6, see 556
+ $isFixedPropertyTable = false;
+ $indexField = '';
+ $sortKeys = [];
+ $property = $dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $description = $descriptionFactory->newSomeProperty(
+ $property,
+ $descriptionFactory->newDisjunction( [
+ $descriptionFactory->newValueDescription( $dataItemFactory->newDIBlob( 'Bar' ) ),
+ $descriptionFactory->newValueDescription( $dataItemFactory->newDIBlob( 'Baz' ) )
+ ] )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinTable = 'FooPropTable';
+ $expected->components = [ 1 => "t0.p_id" ];
+ $expected->queryNumber = 0;
+ $expected->where = '((t0.=fixedFooWhereCond) OR (t0.=fixedFooWhereCond))';
+ $expected->sortfields = [];
+ $expected->from = '';
+
+ $provider[] = [
+ $description,
+ $isFixedPropertyTable,
+ $indexField,
+ $sortKeys,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php
new file mode 100644
index 00000000..5e59430a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ThingDescriptionInterpreterTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\ThingDescriptionInterpreter;
+use SMW\SQLStore\QueryEngineFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\ThingDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ThingDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\ThingDescriptionInterpreter',
+ new ThingDescriptionInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+ public function testInterpretDescription() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ThingDescription' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $expected = new \stdClass;
+ $expected->type = 0;
+ $expected->queryNumber = 0;
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new ThingDescriptionInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php
new file mode 100644
index 00000000..c5e717a4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/DescriptionInterpreters/ValueDescriptionInterpreterTest.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\DescriptionInterpreters;
+
+use SMW\DataItemFactory;
+use SMW\Query\DescriptionFactory;
+use SMW\SQLStore\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter;
+use SMW\SQLStore\QueryEngineFactory;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ValueDescriptionInterpreterTest extends \PHPUnit_Framework_TestCase {
+
+ private $querySegmentValidator;
+ private $descriptionFactory;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->descriptionFactory = new DescriptionFactory();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\DescriptionInterpreters\ValueDescriptionInterpreter',
+ new ValueDescriptionInterpreter( $querySegmentListBuilder )
+ );
+ }
+
+ /**
+ * @dataProvider descriptionProvider
+ */
+ public function testInterpretDescription( $description, $expected ) {
+
+ $objectIds = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPageID' ] )
+ ->getMock();
+
+ $objectIds->expects( $this->any() )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIds ) );
+
+ $queryEngineFactory = new QueryEngineFactory( $store );
+
+ $instance = new ValueDescriptionInterpreter(
+ $queryEngineFactory->newQuerySegmentListBuilder()
+ );
+
+ $this->assertTrue(
+ $instance->canInterpretDescription( $description )
+ );
+
+ $this->querySegmentValidator->assertThatContainerHasProperties(
+ $expected,
+ $instance->interpretDescription( $description )
+ );
+ }
+
+ public function descriptionProvider() {
+
+ $descriptionFactory = new DescriptionFactory();
+ $dataItemFactory = new DataItemFactory();
+
+ #0 SMW_CMP_EQ
+ $description = $descriptionFactory->newValueDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_EQ
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 2;
+ $expected->alias = "t0";
+ $expected->joinfield = [ 42 ];
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ #1 SMW_CMP_LEQ
+ $description = $descriptionFactory->newValueDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_LEQ
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->alias = "t0";
+ $expected->joinfield = "t0.smw_id";
+ $expected->where = "t0.smw_sortkey<=Foo";
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ #2 SMW_CMP_LIKE
+ $description = $descriptionFactory->newValueDescription(
+ $dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN ), null, SMW_CMP_LIKE
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->alias = "t0";
+ $expected->joinfield = "t0.smw_id";
+ $expected->where = "t0.smw_sortkey LIKE Foo";
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ #3 not a DIWikiPage
+ $description = $descriptionFactory->newValueDescription(
+ $dataItemFactory->newDIBLob( 'Foo' )
+ );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->joinfield = "";
+ $expected->where = "";
+
+ $provider[] = [
+ $description,
+ $expected
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/EngineOptionsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/EngineOptionsTest.php
new file mode 100644
index 00000000..184c0390
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/EngineOptionsTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\EngineOptions;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\EngineOptions
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class EngineOptionsTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\EngineOptions',
+ new EngineOptions()
+ );
+ }
+
+ public function testInitialState() {
+
+ $instance = new EngineOptions();
+
+ $this->assertInternalType(
+ 'boolean',
+ $instance->get( 'smwgIgnoreQueryErrors' )
+ );
+
+ $this->assertInternalType(
+ 'integer',
+ $instance->get( 'smwgQSortFeatures' )
+ );
+ }
+
+ public function testAddOption() {
+
+ $instance = new EngineOptions();
+
+ $this->assertFalse(
+ $instance->has( 'Foo' )
+ );
+
+ $instance->set( 'Foo', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->get( 'Foo' )
+ );
+ }
+
+ public function testUnregisteredKeyThrowsException() {
+
+ $instance = new EngineOptions();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->get( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/MySQLValueMatchConditionBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/MySQLValueMatchConditionBuilderTest.php
new file mode 100644
index 00000000..5b15ce67
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/MySQLValueMatchConditionBuilderTest.php
@@ -0,0 +1,213 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\DataItemFactory;
+use SMW\SQLStore\QueryEngine\Fulltext\MySQLValueMatchConditionBuilder;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\MySQLValueMatchConditionBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class MySQLValueMatchConditionBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $textSanitizer;
+ private $searchTable;
+ private $dataItemFactory;
+
+ protected function setUp() {
+
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->textSanitizer = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTable = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\MySQLValueMatchConditionBuilder',
+ new MySQLValueMatchConditionBuilder( $this->textSanitizer, $this->searchTable )
+ );
+ }
+
+ public function testIsEnabled() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new MySQLValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertTrue(
+ $instance->isEnabled()
+ );
+ }
+
+ public function testGetTableName() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'getTableName' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new MySQLValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getTableName()
+ );
+ }
+
+ public function testGetSortIndexField() {
+
+ $this->searchTable->expects( $this->any() )
+ ->method( 'getSortField' )
+ ->will( $this->returnValue( 's_id' ) );
+
+ $instance = new MySQLValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertEquals(
+ 'Foo.s_id',
+ $instance->getSortIndexField( 'Foo' )
+ );
+ }
+
+ public function testCanApplyFulltextSearchMatchCondition() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isValidByType' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'hasMinTokenLength' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isExemptedProperty' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new MySQLValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Foo' ) ) );
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar' ) ) );
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $this->assertTrue(
+ $instance->canApplyFulltextSearchMatchCondition( $description )
+ );
+
+ $instance->getWhereCondition( $description );
+ }
+
+ /**
+ * @dataProvider searchTermProvider
+ */
+ public function testGetWhereConditionWithoutProperty( $text, $indexField, $expected ) {
+
+ $this->textSanitizer->expects( $this->once() )
+ ->method( 'sanitize' )
+ ->will( $this->returnValue( $text ) );
+
+ $this->searchTable->expects( $this->any() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'getIndexField' )
+ ->will( $this->returnValue( $indexField ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new MySQLValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar' ) ) );
+
+ $description->expects( $this->once() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getWhereCondition( $description )
+ );
+ }
+
+ public function searchTermProvider() {
+
+ $provider[] = [
+ 'foooo',
+ 'barColumn',
+ "MATCH(barColumn) AGAINST (foooo IN BOOLEAN MODE) "
+ ];
+
+ $provider[] = [
+ 'foooo&BOL',
+ 'barColumn',
+ "MATCH(barColumn) AGAINST (foooo IN BOOLEAN MODE) "
+ ];
+
+ $provider[] = [
+ 'foooo&INL',
+ 'barColumn',
+ "MATCH(barColumn) AGAINST (foooo IN NATURAL LANGUAGE MODE) "
+ ];
+
+ $provider[] = [
+ 'foooo&QEX',
+ 'barColumn',
+ "MATCH(barColumn) AGAINST (foooo WITH QUERY EXPANSION) "
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SQLiteValueMatchConditionBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SQLiteValueMatchConditionBuilderTest.php
new file mode 100644
index 00000000..7935f70b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SQLiteValueMatchConditionBuilderTest.php
@@ -0,0 +1,236 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\DataItemFactory;
+use SMW\SQLStore\QueryEngine\Fulltext\SQLiteValueMatchConditionBuilder;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\SQLiteValueMatchConditionBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SQLiteValueMatchConditionBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $textSanitizer;
+ private $searchTable;
+ private $dataItemFactory;
+
+ protected function setUp() {
+
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->textSanitizer = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTable = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\SQLiteValueMatchConditionBuilder',
+ new SQLiteValueMatchConditionBuilder( $this->textSanitizer, $this->searchTable )
+ );
+ }
+
+ public function testIsEnabled() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new SQLiteValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertTrue(
+ $instance->isEnabled()
+ );
+ }
+
+ public function testGetTableName() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'getTableName' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new SQLiteValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getTableName()
+ );
+ }
+
+ public function testGetSortIndexField() {
+
+ $this->searchTable->expects( $this->any() )
+ ->method( 'getSortField' )
+ ->will( $this->returnValue( 's_id' ) );
+
+ $instance = new SQLiteValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertEquals(
+ 'Foo.s_id',
+ $instance->getSortIndexField( 'Foo' )
+ );
+ }
+
+ public function testCanApplyFulltextSearchMatchCondition() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isValidByType' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'hasMinTokenLength' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isExemptedProperty' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new SQLiteValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Foo' ) ) );
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar' ) ) );
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $this->assertTrue(
+ $instance->canApplyFulltextSearchMatchCondition( $description )
+ );
+
+ $instance->getWhereCondition( $description );
+ }
+
+ public function testGetWhereConditionWithPropertyOnTempTable() {
+
+ $this->textSanitizer->expects( $this->once() )
+ ->method( 'sanitize' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'getIndexField' )
+ ->will( $this->returnValue( 'indexField' ) );
+
+ $this->searchTable->expects( $this->atLeastOnce() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new SQLiteValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getProperty' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIProperty( 'Foo' ) ) );
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar' ) ) );
+
+ $description->expects( $this->once() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $this->assertSame(
+ 'tempTable.indexField MATCH Foo AND tempTable.p_id=',
+ $instance->getWhereCondition( $description, 'tempTable' )
+ );
+ }
+
+ /**
+ * @dataProvider searchTermProvider
+ */
+ public function testGetWhereConditionWithoutProperty( $text, $indexField, $expected ) {
+
+ $this->textSanitizer->expects( $this->once() )
+ ->method( 'sanitize' )
+ ->will( $this->returnValue( $text ) );
+
+ $this->searchTable->expects( $this->any() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'getIndexField' )
+ ->will( $this->returnValue( $indexField ) );
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $instance = new SQLiteValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $description->expects( $this->atLeastOnce() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar' ) ) );
+
+ $description->expects( $this->once() )
+ ->method( 'getComparator' )
+ ->will( $this->returnValue( SMW_CMP_LIKE ) );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getWhereCondition( $description )
+ );
+ }
+
+ public function searchTermProvider() {
+
+ $provider[] = [
+ 'foooo',
+ 'barColumn',
+ "barColumn MATCH foooo"
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableRebuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableRebuilderTest.php
new file mode 100644
index 00000000..cb5da767
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableRebuilderTest.php
@@ -0,0 +1,218 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\SQLStore\QueryEngine\Fulltext\SearchTableRebuilder;
+use SMW\Tests\Utils\Mock\IteratorMockBuilder;
+use SMWDataItem as DataItem;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\SearchTableRebuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SearchTableRebuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $searchTableUpdater;
+ private $searchTable;
+ private $connection;
+ private $iteratorMockBuilder;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTable = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTableUpdater->expects( $this->any() )
+ ->method( 'getSearchTable' )
+ ->will( $this->returnValue( $this->searchTable ) );
+
+ $this->iteratorMockBuilder = new IteratorMockBuilder();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\SearchTableRebuilder',
+ new SearchTableRebuilder( $this->connection, $this->searchTableUpdater )
+ );
+ }
+
+ public function testRebuildWithoutUpdate() {
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableDefinition->expects( $this->atLeastOnce() )
+ ->method( 'getDiType' )
+ ->will( $this->returnValue( DataItem::TYPE_BLOB ) );
+
+ $this->searchTableUpdater->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $tableDefinition ] ) );
+
+ $instance = new SearchTableRebuilder(
+ $this->connection,
+ $this->searchTableUpdater
+ );
+
+ $instance->rebuild();
+ }
+
+ public function testNeverRebuildOnOptimization() {
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTableUpdater->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTableUpdater->expects( $this->never() )
+ ->method( 'getPropertyTables' );
+
+ $this->searchTableUpdater->expects( $this->once() )
+ ->method( 'optimize' );
+
+ $instance = new SearchTableRebuilder(
+ $this->connection,
+ $this->searchTableUpdater
+ );
+
+ $instance->requestOptimization( true );
+
+ $instance->rebuild();
+ }
+
+ public function testRebuildWithUpdateOnBlob() {
+
+ $row = new \stdClass;
+ $row->o_serialized = 'Foo';
+ $row->o_blob = null;
+ $row->s_id = 42;
+
+ $resultWrapper = $this->iteratorMockBuilder->setClass( '\ResultWrapper' )
+ ->with( [ $row ] )
+ ->incrementInvokedCounterBy( 1 )
+ ->getMockForIterator();
+
+ $resultWrapper->expects( $this->atLeastOnce() )
+ ->method( 'numRows' )
+ ->will( $this->returnValue( 1 ) );
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'select' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $tableDefinition = $this->getMockBuilder( '\SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableDefinition->expects( $this->atLeastOnce() )
+ ->method( 'getDiType' )
+ ->will( $this->returnValue( DataItem::TYPE_BLOB ) );
+
+ $this->searchTable->expects( $this->any() )
+ ->method( 'isValidByType' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTable->expects( $this->any() )
+ ->method( 'hasMinTokenLength' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTableUpdater->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $tableDefinition ] ) );
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'update' )
+ ->with( $this->equalTo( $row->s_id ) );
+
+ $instance = new SearchTableRebuilder(
+ $this->connection,
+ $this->searchTableUpdater
+ );
+
+ $instance->reportVerbose( true );
+ $instance->rebuild();
+ }
+
+ public function testgetQualifiedTableList() {
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDefinition->expects( $this->atLeastOnce() )
+ ->method( 'getDiType' )
+ ->will( $this->returnValue( DataItem::TYPE_BLOB ) );
+
+ $this->searchTableUpdater->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $propertyTableDefinition ] ) );
+
+ $instance = new SearchTableRebuilder(
+ $this->connection,
+ $this->searchTableUpdater
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getQualifiedTableList()
+ );
+ }
+
+ public function testRebuildByTable() {
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableDefinition->expects( $this->atLeastOnce() )
+ ->method( 'getName' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $propertyTableDefinition->expects( $this->atLeastOnce() )
+ ->method( 'getDiType' )
+ ->will( $this->returnValue( DataItem::TYPE_BLOB ) );
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $propertyTableDefinition ] ) );
+
+ $instance = new SearchTableRebuilder(
+ $this->connection,
+ $this->searchTableUpdater
+ );
+
+ $instance->rebuildByTable( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableTest.php
new file mode 100644
index 00000000..7b2c0036
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableTest.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\DataItemFactory;
+use SMW\SQLStore\QueryEngine\Fulltext\SearchTable;
+use SMWDataItem as DataItem;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\SearchTable
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SearchTableTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $dataItemFactory;
+
+ protected function setUp() {
+
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable',
+ new SearchTable( $this->store )
+ );
+ }
+
+ public function testIsEnabled() {
+
+ $instance = new SearchTable(
+ $this->store
+ );
+
+ $instance->setEnabled( true );
+
+ $this->assertTrue(
+ $instance->isEnabled()
+ );
+ }
+
+ public function testGetPropertyExemptionList() {
+
+ $instance = new SearchTable(
+ $this->store
+ );
+
+ $instance->setPropertyExemptionList(
+ [ '_TEXT','fo oo' ]
+ );
+
+ $this->assertEquals(
+ [ '_TEXT', 'fo_oo' ],
+ $instance->getPropertyExemptionList()
+ );
+ }
+
+ public function testIsExemptedProperty() {
+
+ $instance = new SearchTable(
+ $this->store
+ );
+
+ $instance->setIndexableDataTypes(
+ SMW_FT_BLOB | SMW_FT_URI
+ );
+
+ $instance->setPropertyExemptionList(
+ [ '_TEXT' ]
+ );
+
+ $property = $this->dataItemFactory->newDIProperty( '_TEXT' );
+
+ $this->assertTrue(
+ $instance->isExemptedProperty( $property )
+ );
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $property->setPropertyTypeId( '_uri' );
+
+ $this->assertFalse(
+ $instance->isExemptedProperty( $property )
+ );
+ }
+
+ public function testIsValidType() {
+
+ $instance = new SearchTable(
+ $this->store
+ );
+
+ $instance->setIndexableDataTypes(
+ SMW_FT_BLOB | SMW_FT_URI
+ );
+
+ $this->assertTrue(
+ $instance->isValidByType( DataItem::TYPE_BLOB )
+ );
+
+ $this->assertFalse(
+ $instance->isValidByType( DataItem::TYPE_WIKIPAGE )
+ );
+ }
+
+ public function testHasMinTokenLength() {
+
+ $instance = new SearchTable(
+ $this->store
+ );
+
+ $instance->setMinTokenSize( 4 );
+
+ $this->assertFalse(
+ $instance->hasMinTokenLength( 'bar' )
+ );
+
+ $this->assertFalse(
+ $instance->hasMinTokenLength( 'テスト' )
+ );
+
+ $this->assertTrue(
+ $instance->hasMinTokenLength( 'test' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableUpdaterTest.php
new file mode 100644
index 00000000..bdd716c1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/SearchTableUpdaterTest.php
@@ -0,0 +1,215 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\SQLStore\QueryEngine\Fulltext\SearchTableUpdater;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\SearchTableUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SearchTableUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+ private $searchTable;
+ private $textSanitizer;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTable = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->textSanitizer = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\SearchTableUpdater',
+ new SearchTableUpdater( $this->connection, $this->searchTable, $this->textSanitizer )
+ );
+ }
+
+ public function testRead() {
+
+ $row = new \stdClass;
+ $row->o_text = 'Foo';
+
+ $this->connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'o_text' ] ),
+ $this->equalTo( [ 's_id' => 12, 'p_id' => 42 ] ) )
+ ->will( $this->returnValue( $row ) );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $instance->read( 12, 42 );
+ }
+
+ public function testOptimizeOnEnabledType() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'isType' )
+ ->with( $this->equalTo( 'mysql' ) )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $this->assertTrue(
+ $instance->optimize()
+ );
+ }
+
+ public function testOptimizeOnDisabledType() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'isType' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->never() )
+ ->method( 'query' );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $this->assertFalse(
+ $instance->optimize()
+ );
+ }
+
+ public function testUpdateWithText() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'update' );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $instance->update( 12, 42, 'foo' );
+ }
+
+ public function testDeleteOnUpdateWithEmptyText() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'delete' );
+
+ $this->connection->expects( $this->never() )
+ ->method( 'update' );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $instance->update( 12, 42, ' ' );
+ }
+
+ public function testInsert() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'insert' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [
+ 's_id' => 12,
+ 'p_id' => 42,
+ 'o_text' => '' ] ) );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $instance->insert( 12, 42 );
+ }
+
+ public function testDelete() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'delete' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [
+ 's_id' => 12,
+ 'p_id' => 42 ] ) );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $instance->delete( 12, 42 );
+ }
+
+ public function testFlushTable() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'delete' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( '*' ) );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $instance->flushTable();
+ }
+
+ public function testExists() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [
+ 's_id' => 12,
+ 'p_id' => 42 ] ) );
+
+ $instance = new SearchTableUpdater(
+ $this->connection,
+ $this->searchTable,
+ $this->textSanitizer
+ );
+
+ $instance->exists( 12, 42 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextChangeUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextChangeUpdaterTest.php
new file mode 100644
index 00000000..29b3156f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextChangeUpdaterTest.php
@@ -0,0 +1,204 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\DataItemFactory;
+use SMW\SQLStore\QueryEngine\Fulltext\TextChangeUpdater;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\TextChangeUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TextChangeUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ private $dataItemFactory;
+ private $connection;
+ private $searchTableUpdater;
+ private $cache;
+ private $slot;
+ private $logger;
+ private $testEnvironment;
+
+ protected function setUp() {
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->logger = TestEnvironment::newSpyLogger();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobFactory', $this->jobFactory );
+
+ $this->slot = '';
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TextChangeUpdater::class,
+ new TextChangeUpdater( $this->connection, $this->cache, $this->searchTableUpdater )
+ );
+ }
+
+ public function testPushUpdatesOnNullChange() {
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $changeDiff = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeDiff' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->never() )
+ ->method( 'getSubject' );
+
+ $instance = new TextChangeUpdater(
+ $this->connection,
+ $this->cache,
+ $this->searchTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->logger
+ );
+
+ $instance->pushUpdates(
+ $changeOp
+ );
+ }
+
+ public function testPushUpdates() {
+
+ $dataItem = $this->dataItemFactory->newDIWikiPage( 'Foo', NS_MAIN );
+
+ $searchTable = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $searchTable->expects( $this->atLeastOnce() )
+ ->method( 'getDataItemById' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIWikiPage( 'Bar', SMW_NS_PROPERTY ) ) );
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'getSearchTable' )
+ ->will( $this->returnValue( $searchTable ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [ '42' ] ) );
+
+ $changeOp->expects( $this->atLeastOnce() )
+ ->method( 'getSubject' )
+ ->will( $this->returnValue( $dataItem ) );
+
+ $nullJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\NullJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->jobFactory->expects( $this->once() )
+ ->method( 'newFulltextSearchTableUpdateJob' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'slot:id' => 'Foo#0##' ] ) )
+ ->will( $this->returnValue( $nullJob ) );
+
+ $instance = new TextChangeUpdater(
+ $this->connection,
+ $this->cache,
+ $this->searchTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->logger
+ );
+
+ $instance->pushUpdates(
+ $changeOp
+ );
+ }
+
+ public function testPushUpdatesDirectlyWhenExecutedFromCommandLine() {
+
+ $this->searchTableUpdater->expects( $this->atLeastOnce() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( true ) );
+
+ $changeDiff = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeDiff' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff->expects( $this->once() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeDiff->expects( $this->once() )
+ ->method( 'getTextItems' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->once() )
+ ->method( 'newChangeDiff' )
+ ->will( $this->returnValue( $changeDiff ) );
+
+ $changeOp->expects( $this->never() )
+ ->method( 'getSubject' );
+
+ $instance = new TextChangeUpdater(
+ $this->connection,
+ $this->cache,
+ $this->searchTableUpdater
+ );
+
+ $instance->setLogger(
+ $this->logger
+ );
+
+ $instance->isCommandLineMode( true );
+
+ $instance->pushUpdates(
+ $changeOp
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextSanitizerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextSanitizerTest.php
new file mode 100644
index 00000000..4e720e61
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/TextSanitizerTest.php
@@ -0,0 +1,136 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TextSanitizerTest extends \PHPUnit_Framework_TestCase {
+
+ private $sanitizerFactory;
+
+ protected function setUp() {
+
+ $this->sanitizerFactory = $this->getMockBuilder( '\Onoi\Tesa\SanitizerFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer',
+ new TextSanitizer( $this->sanitizerFactory )
+ );
+ }
+
+ /**
+ * @dataProvider textOnMockProvider
+ */
+ public function testSanitizs( $text, $expected ) {
+
+ $sanitizer = $this->getMockBuilder( '\Onoi\Tesa\Sanitizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $sanitizer->expects( $this->atLeastOnce() )
+ ->method( 'sanitizeWith' )
+ ->will( $this->returnValue( $text ) );
+
+ $stopwordAnalyzer = $this->getMockBuilder( '\Onoi\Tesa\StopwordAnalyzer\StopwordAnalyzer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $synonymizer = $this->getMockBuilder( '\Onoi\Tesa\Synonymizer\Synonymizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tokenizer = $this->getMockBuilder( '\Onoi\Tesa\Tokenizer\Tokenizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->sanitizerFactory->expects( $this->atLeastOnce() )
+ ->method( 'newSanitizer' )
+ ->will( $this->returnValue( $sanitizer ) );
+
+ $this->sanitizerFactory->expects( $this->atLeastOnce() )
+ ->method( 'newPreferredTokenizerByLanguage' )
+ ->will( $this->returnValue( $tokenizer ) );
+
+ $this->sanitizerFactory->expects( $this->atLeastOnce() )
+ ->method( 'newStopwordAnalyzerByLanguage' )
+ ->will( $this->returnValue( $stopwordAnalyzer ) );
+
+ $this->sanitizerFactory->expects( $this->atLeastOnce() )
+ ->method( 'newSynonymizerByLanguage' )
+ ->will( $this->returnValue( $synonymizer ) );
+
+ $instance = new TextSanitizer(
+ $this->sanitizerFactory
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->sanitize( $text )
+ );
+ }
+
+ public function textOnMockProvider() {
+
+ $provider[] = [
+ 'foo',
+ 'foo'
+ ];
+
+ $provider[] = [
+ 'foo* - bar',
+ 'foo* -bar'
+ ];
+
+ $provider[] = [
+ 'foo* + bar',
+ 'foo* +bar'
+ ];
+
+ $provider[] = [
+ 'foo *',
+ 'foo*'
+ ];
+
+ $provider[] = [
+ '* foo *',
+ '*foo*'
+ ];
+
+ $provider[] = [
+ '*foo* bar',
+ '*foo*bar'
+ ];
+
+ $provider[] = [
+ '+foo*, *bar',
+ '+foo*,*bar'
+ ];
+
+ $provider[] = [
+ '+foo* -bar',
+ '+foo* -bar'
+ ];
+
+ $provider[] = [
+ '+foo* ~ bar',
+ '+foo* ~bar'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/ValueMatchConditionBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/ValueMatchConditionBuilderTest.php
new file mode 100644
index 00000000..b61e61e3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/Fulltext/ValueMatchConditionBuilderTest.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine\Fulltext;
+
+use SMW\DataItemFactory;
+use SMW\SQLStore\QueryEngine\Fulltext\ValueMatchConditionBuilder;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\Fulltext\ValueMatchConditionBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ValueMatchConditionBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $textSanitizer;
+ private $searchTable;
+ private $dataItemFactory;
+
+ protected function setUp() {
+
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->textSanitizer = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchTable = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\ValueMatchConditionBuilder',
+ new ValueMatchConditionBuilder( $this->textSanitizer, $this->searchTable )
+ );
+ }
+
+ public function testIsEnabled() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'isEnabled' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new ValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertFalse(
+ $instance->isEnabled()
+ );
+ }
+
+ public function testGetTableName() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'getTableName' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $instance = new ValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertEquals(
+ 'Foo',
+ $instance->getTableName()
+ );
+ }
+
+ public function testHasMinTokenLength() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'hasMinTokenLength' )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new ValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertFalse(
+ $instance->hasMinTokenLength( 'bar' )
+ );
+ }
+
+ public function testGetSortIndexField() {
+
+ $this->searchTable->expects( $this->once() )
+ ->method( 'getSortField' )
+ ->will( $this->returnValue( 'bar' ) );
+
+ $instance = new ValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $this->assertEquals(
+ 'Foo.bar',
+ $instance->getSortIndexField( 'Foo' )
+ );
+ }
+
+ public function testCanApplyFulltextSearchMatchCondition() {
+
+ $instance = new ValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertFalse(
+ $instance->canApplyFulltextSearchMatchCondition( $description )
+ );
+ }
+
+ public function testGetWhereConditionWithPropertyOnTempTable() {
+
+ $instance = new ValueMatchConditionBuilder(
+ $this->textSanitizer,
+ $this->searchTable
+ );
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\ValueDescription' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertSame(
+ '',
+ $instance->getWhereCondition( $description )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/FulltextSearchTableFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/FulltextSearchTableFactoryTest.php
new file mode 100644
index 00000000..918f3d2a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/FulltextSearchTableFactoryTest.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\FulltextSearchTableFactory;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\FulltextSearchTableFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FulltextSearchTableFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstructValueMatchConditionBuilderOnUnknownConnectionType() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new FulltextSearchTableFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\ValueMatchConditionBuilder',
+ $instance->newValueMatchConditionBuilderByType( $this->store )
+ );
+ }
+
+ public function testCanConstructValueMatchConditionBuilderOnMySQLConnectionType() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new FulltextSearchTableFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\MySQLValueMatchConditionBuilder',
+ $instance->newValueMatchConditionBuilderByType( $this->store )
+ );
+ }
+
+ public function testCanConstructTextSanitizer() {
+
+ $instance = new FulltextSearchTableFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\TextSanitizer',
+ $instance->newTextSanitizer()
+ );
+ }
+
+ public function testCanConstructSearchTable() {
+
+ $instance = new FulltextSearchTableFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\SearchTable',
+ $instance->newSearchTable( $this->store )
+ );
+ }
+
+ public function testCanConstructSearchTableUpdater() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new FulltextSearchTableFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\SearchTableUpdater',
+ $instance->newSearchTableUpdater( $this->store )
+ );
+ }
+
+ public function testCanConstructTextChangeUpdater() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new FulltextSearchTableFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\TextChangeUpdater',
+ $instance->newTextChangeUpdater( $this->store )
+ );
+ }
+
+ public function testCanConstructSearchTableRebuilder() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new FulltextSearchTableFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\Fulltext\SearchTableRebuilder',
+ $instance->newSearchTableRebuilder( $this->store )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/HierarchyTempTableBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/HierarchyTempTableBuilderTest.php
new file mode 100644
index 00000000..b01b114e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/HierarchyTempTableBuilderTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\HierarchyTempTableBuilder;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\HierarchyTempTableBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class HierarchyTempTableBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $connection;
+ private $temporaryTableBuilder;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->temporaryTableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\TemporaryTableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\HierarchyTempTableBuilder',
+ new HierarchyTempTableBuilder( $this->connection, $this->temporaryTableBuilder )
+ );
+ }
+
+ public function testGetHierarchyTableDefinitionForType() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableName' )
+ ->with(
+ $this->stringContains( 'bar') )
+ ->will( $this->returnValue( '_bar' ) );
+
+ $instance = new HierarchyTempTableBuilder(
+ $this->connection,
+ $this->temporaryTableBuilder
+ );
+
+ $instance->setPropertyHierarchyTableDefinition( 'bar', 3 );
+
+ $this->assertEquals(
+ [ '_bar', 3 ],
+ $instance->getHierarchyTableDefinitionForType( 'property' )
+ );
+ }
+
+ public function testTryToGetHierarchyTableDefinitionForUnregisteredTypeThrowsException() {
+
+ $instance = new HierarchyTempTableBuilder(
+ $this->connection,
+ $this->temporaryTableBuilder
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->getHierarchyTableDefinitionForType( 'foo' );
+ }
+
+ public function testCreateHierarchyTempTable() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableName' )
+ ->with(
+ $this->stringContains( 'bar') )
+ ->will( $this->returnValue( '_bar' ) );
+
+ $this->connection->expects( $this->atLeastOnce() )
+ ->method( 'query' );
+
+ $instance = new HierarchyTempTableBuilder(
+ $this->connection,
+ $this->temporaryTableBuilder
+ );
+
+ $instance->setClassHierarchyTableDefinition( 'bar', 3 );
+ $instance->createHierarchyTempTableFor( 'class', 'foobar', '(42)' );
+
+ $expected = [
+ '(42)' => 'foobar'
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getHierarchyCache()
+ );
+
+ $instance->emptyHierarchyCache();
+
+ $this->assertEmpty(
+ $instance->getHierarchyCache()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/OrderConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/OrderConditionTest.php
new file mode 100644
index 00000000..aca77277
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/OrderConditionTest.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\OrderCondition;
+use SMW\SQLStore\QueryEngine\QuerySegment;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\OrderCondition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class OrderConditionTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $querySegmentListBuilder;
+
+ protected function setUp() {
+
+ $this->querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ OrderCondition::class,
+ new OrderCondition( $this->querySegmentListBuilder )
+ );
+ }
+
+ public function testApplyWithoutSortKey() {
+
+ $this->querySegmentListBuilder->expects( $this->once() )
+ ->method( 'getQuerySegmentList' );
+
+ $instance = new OrderCondition(
+ $this->querySegmentListBuilder
+ );
+
+ $instance->apply( 42 );
+ }
+
+ /**
+ * @dataProvider sortKeyProvider
+ */
+ public function testApplyWithSortKey( $sortKeys ) {
+
+ $querySegment = new QuerySegment();
+
+ $this->querySegmentListBuilder->expects( $this->once() )
+ ->method( 'getQuerySegmentList' );
+
+ $this->querySegmentListBuilder->expects( $this->atLeastOnce() )
+ ->method( 'findQuerySegment' )
+ ->will( $this->returnValue( $querySegment ) );
+
+ $instance = new OrderCondition(
+ $this->querySegmentListBuilder
+ );
+
+ $instance->setSortKeys( $sortKeys );
+
+ $instance->apply( 42 );
+ $querySegment->reset();
+ }
+
+ public function testApplyWithInvalidSortKeyThrowsException() {
+
+ $querySegment = new QuerySegment();
+
+ $this->querySegmentListBuilder->expects( $this->never() )
+ ->method( 'getQuerySegmentList' );
+
+ $this->querySegmentListBuilder->expects( $this->atLeastOnce() )
+ ->method( 'findQuerySegment' )
+ ->will( $this->returnValue( $querySegment ) );
+
+ $instance = new OrderCondition(
+ $this->querySegmentListBuilder
+ );
+
+ $instance->setSortKeys( [
+ 42 => 'ASC'
+ ]
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->apply( 42 );
+
+ $querySegment->reset();
+ }
+
+ public function sortKeyProvider() {
+
+ $provider[] = [
+ [
+ '' => 'ASC'
+ ]
+ ];
+
+ $provider[] = [
+ [
+ '#' => 'DESC'
+ ]
+ ];
+
+ $provider[] = [
+ [
+ 'Foo' => 'ASC'
+ ]
+ ];
+
+ $provider[] = [
+ [
+ 'Foo.bar' => 'ASC'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QueryEngineTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QueryEngineTest.php
new file mode 100644
index 00000000..93c03f10
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QueryEngineTest.php
@@ -0,0 +1,119 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\QueryEngine;
+use SMWQuery as Query;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\QueryEngine
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class QueryEngineTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $querySegmentListBuildManager;
+ private $querySegmentListProcessor;
+ private $engineOptions;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->querySegmentListBuildManager = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuildManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->querySegmentListProcessor = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListProcessor' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->engineOptions = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\EngineOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QueryEngine',
+ new QueryEngine( $this->store, $this->querySegmentListBuildManager, $this->querySegmentListProcessor, $this->engineOptions )
+ );
+ }
+
+ public function testGetQueryResultForDebugQueryMode() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->querySegmentListBuildManager->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->querySegmentListProcessor->expects( $this->any() )
+ ->method( 'getExecutedQueries' )
+ ->will( $this->returnValue( [] ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $this->store,
+ $this->querySegmentListBuildManager,
+ $this->querySegmentListProcessor,
+ $this->engineOptions
+ );
+
+ $query = new Query( $description );
+ $query->querymode = Query::MODE_DEBUG;
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+ public function testGetImmediateEmptyQueryResultForLimitLessThanOne() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->never() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->querySegmentListBuildManager->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [] ) );
+
+ $description = $this->getMockForAbstractClass( '\SMW\Query\Language\Description' );
+
+ $instance = new QueryEngine(
+ $this->store,
+ $this->querySegmentListBuildManager,
+ $this->querySegmentListProcessor,
+ $this->engineOptions
+ );
+
+ $query = new Query( $description );
+ $query->setUnboundLimit( -1 );
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ $instance->getQueryResult( $query )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuildManagerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuildManagerTest.php
new file mode 100644
index 00000000..6245b2b9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuildManagerTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\QuerySegmentListBuildManager;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\QuerySegmentListBuildManager
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QuerySegmentListBuildManagerTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+ private $querySegmentListBuilder;
+ private $orderCondition;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->querySegmentListBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->orderCondition = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\OrderCondition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ QuerySegmentListBuildManager::class,
+ new QuerySegmentListBuildManager( $this->connection, $this->querySegmentListBuilder, $this->orderCondition )
+ );
+ }
+
+ public function testGetQuerySegmentFrom() {
+
+ $description = $this->getMockBuilder( '\SMW\Query\Language\Description' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $query->expects( $this->atLeastOnce() )
+ ->method( 'getDescription' )
+ ->will( $this->returnValue( $description ) );
+
+ $this->querySegmentListBuilder->expects( $this->once() )
+ ->method( 'getQuerySegmentFrom' );
+
+ $this->orderCondition->expects( $this->once() )
+ ->method( 'apply' );
+
+ $instance = new QuerySegmentListBuildManager(
+ $this->connection,
+ $this->querySegmentListBuilder,
+ $this->orderCondition
+ );
+
+ $instance->getQuerySegmentFrom( $query );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuilderTest.php
new file mode 100644
index 00000000..e61a2909
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListBuilderTest.php
@@ -0,0 +1,293 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\DIWikiPage;
+use SMW\Query\Language\ClassDescription;
+use SMW\Query\Language\Disjunction;
+use SMW\Query\Language\NamespaceDescription;
+use SMW\SQLStore\QueryEngine\DescriptionInterpreterFactory;
+use SMW\SQLStore\QueryEngine\QuerySegment;
+use SMW\SQLStore\QueryEngine\QuerySegmentListBuilder;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\QuerySegmentListBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class QuerySegmentListBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $querySegmentValidator;
+ private $descriptionInterpreterFactory;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->descriptionInterpreterFactory = new DescriptionInterpreterFactory();
+
+ $testEnvironment = new TestEnvironment();
+ $this->querySegmentValidator = $testEnvironment->getUtilityFactory()->newValidatorFactory()->newQuerySegmentValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $descriptionInterpreterFactory = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\DescriptionInterpreterFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder',
+ new QuerySegmentListBuilder( $this->store, $descriptionInterpreterFactory )
+ );
+ }
+
+ public function testNamespaceDescription() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $description = new NamespaceDescription( NS_HELP );
+
+ $instance = new QuerySegmentListBuilder(
+ $store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $instance->getQuerySegmentFrom( $description );
+
+ $expected = new \stdClass;
+ $expected->type = 1;
+ $expected->where = "t0.smw_namespace=";
+
+ $this->assertEquals( 0, $instance->getLastQuerySegmentId() );
+ $this->assertEmpty( $instance->getErrors() );
+
+ $this->querySegmentValidator->assertThatContainerContains(
+ $expected,
+ $instance->getQuerySegmentList()
+ );
+ }
+
+ public function testDisjunctiveNamespaceDescription() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $description = new Disjunction();
+ $description->addDescription( new NamespaceDescription( NS_HELP ) );
+ $description->addDescription( new NamespaceDescription( NS_MAIN ) );
+
+ $instance = new QuerySegmentListBuilder(
+ $store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $instance->getQuerySegmentFrom( $description );
+
+ $expectedDisjunction = new \stdClass;
+ $expectedDisjunction->type = 3;
+
+ $expectedHelpNs = new \stdClass;
+ $expectedHelpNs->type = 1;
+ $expectedHelpNs->where = "t1.smw_namespace=";
+
+ $expectedMainNs = new \stdClass;
+ $expectedMainNs->type = 1;
+ $expectedMainNs->where = "t2.smw_namespace=";
+
+ $this->assertEquals(
+ 0,
+ $instance->getLastQuerySegmentId()
+ );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+
+ $expected = [
+ $expectedDisjunction,
+ $expectedHelpNs,
+ $expectedMainNs
+ ];
+
+ $this->querySegmentValidator->assertThatContainerContains(
+ $expected,
+ $instance->getQuerySegmentList()
+ );
+ }
+
+ public function testClassDescription() {
+
+ $objectIds = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getSMWPageID' ] )
+ ->getMock();
+
+ $objectIds->expects( $this->any() )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 42 ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIds ) );
+
+ $description = new ClassDescription( new DIWikiPage( 'Foo', NS_CATEGORY ) );
+
+ $instance = new QuerySegmentListBuilder(
+ $store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $instance->getQuerySegmentFrom( $description );
+
+ $expectedClass = new \stdClass;
+ $expectedClass->type = 1;
+ $expectedClass->alias = "t0";
+ $expectedClass->queryNumber = 0;
+
+ $expectedHierarchy = new \stdClass;
+ $expectedHierarchy->type = 5;
+ $expectedHierarchy->joinfield = [ 0 => 42 ];
+ $expectedHierarchy->alias = "t1";
+ $expectedHierarchy->queryNumber = 1;
+
+ $this->assertEquals(
+ 0,
+ $instance->getLastQuerySegmentId()
+ );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+
+ $expected = [
+ $expectedClass,
+ $expectedHierarchy
+ ];
+
+ $this->querySegmentValidator->assertThatContainerContains(
+ $expected,
+ $instance->getQuerySegmentList()
+ );
+ }
+
+ public function testGivenNonInteger_getQuerySegmentThrowsException() {
+
+ $instance = new QuerySegmentListBuilder(
+ $this->store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->findQuerySegment( null );
+ }
+
+ public function testGivenUnknownId_getQuerySegmentThrowsException() {
+
+ $instance = new QuerySegmentListBuilder(
+ $this->store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+ $instance->findQuerySegment( 1 );
+ }
+
+ public function testGivenKnownId_getQuerySegmentReturnsCorrectPart() {
+
+ $instance = new QuerySegmentListBuilder(
+ $this->store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $querySegment = new QuerySegment();
+
+ // $querySegment->segmentNumber = 1;
+ $instance->addQuerySegment( $querySegment );
+
+ $this->assertSame(
+ $querySegment,
+ $instance->findQuerySegment( $querySegment->queryNumber )
+ );
+ }
+
+ public function testWhenNoQuerySegments_getQuerySegmentListReturnsEmptyArray() {
+
+ $instance = new QuerySegmentListBuilder(
+ $this->store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $this->assertSame(
+ [],
+ $instance->getQuerySegmentList()
+ );
+ }
+
+ public function testWhenSomeQuerySegments_getQuerySegmentListReturnsThemAll() {
+
+ $instance = new QuerySegmentListBuilder(
+ $this->store,
+ $this->descriptionInterpreterFactory
+ );
+
+ $firstQuerySegment = new QuerySegment();
+ $instance->addQuerySegment( $firstQuerySegment );
+
+ $secondQuerySegment = new QuerySegment();
+ $instance->addQuerySegment( $secondQuerySegment );
+
+ $expected = [
+ 0 => $firstQuerySegment,
+ 1 => $secondQuerySegment
+ ];
+
+ $this->assertSame(
+ $expected,
+ $instance->getQuerySegmentList()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListProcessorTest.php
new file mode 100644
index 00000000..9963ac5b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentListProcessorTest.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\QuerySegmentListProcessor;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\QuerySegmentListProcessor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class QuerySegmentListProcessorTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $temporaryTableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\TemporaryTableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $hierarchyTempTableBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\HierarchyTempTableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QuerySegmentListProcessor',
+ new QuerySegmentListProcessor( $connection, $temporaryTableBuilder, $hierarchyTempTableBuilder )
+ );
+ }
+
+ public function testTryResolveSegmentForInvalidIdThrowsException() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $temporaryTableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\TemporaryTableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $hierarchyTempTableBuilder = $this->getMockBuilder( '\SMW\SQLStore\QueryEngine\HierarchyTempTableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QuerySegmentListProcessor(
+ $connection,
+ $temporaryTableBuilder,
+ $hierarchyTempTableBuilder
+ );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->process( 42 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentTest.php
new file mode 100644
index 00000000..f4388a5e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngine/QuerySegmentTest.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace SMW\Tests\SQLStore\QueryEngine;
+
+use SMW\SQLStore\QueryEngine\QuerySegment;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngine\QuerySegment
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class QuerySegmentTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QuerySegment',
+ new QuerySegment()
+ );
+ }
+
+ public function testInitialStateAfterReset() {
+
+ $instance = new QuerySegment();
+ $instance->reset();
+
+ $this->assertEquals(
+ 0,
+ $instance->queryNumber
+ );
+
+ $this->assertEquals(
+ 't0',
+ $instance->alias
+ );
+
+ $this->assertEquals(
+ 1,
+ $instance::$qnum
+ );
+
+ $this->assertEquals(
+ $instance::Q_TABLE,
+ $instance->type
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->components
+ );
+
+ $this->assertEquals(
+ [],
+ $instance->sortfields
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->joinfield
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->joinTable
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->from
+ );
+
+ $this->assertEquals(
+ '',
+ $instance->where
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngineFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngineFactoryTest.php
new file mode 100644
index 00000000..0ba0f83b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/QueryEngineFactoryTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\QueryEngineFactory;
+
+/**
+ * @covers \SMW\SQLStore\QueryEngineFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class QueryEngineFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngineFactory',
+ new QueryEngineFactory( $store )
+ );
+ }
+
+ public function testCanConstructQuerySegmentListBuilder() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new QueryEngineFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QuerySegmentListBuilder',
+ $instance->newQuerySegmentListBuilder()
+ );
+ }
+
+ public function testCanConstructQuerySegmentListProcessor() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new QueryEngineFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QuerySegmentListProcessor',
+ $instance->newQuerySegmentListProcessor()
+ );
+ }
+
+ public function testCanConstructQueryEngine() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new QueryEngineFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QueryEngine',
+ $instance->newQueryEngine()
+ );
+ }
+
+ public function testCanConstructConceptQuerySegmentBuilder() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new QueryEngineFactory( $store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\ConceptQuerySegmentBuilder',
+ $instance->newConceptQuerySegmentBuilder()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RedirectStoreTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RedirectStoreTest.php
new file mode 100644
index 00000000..f14bdd61
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RedirectStoreTest.php
@@ -0,0 +1,265 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\InMemoryPoolCache;
+use SMW\SQLStore\RedirectStore;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\RedirectStore
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class RedirectStoreTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $conection;
+ private $cache;
+ private $testEnvironment;
+ private $connectionManager;
+
+ protected function setUp() {
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( null )
+ ->getMock();
+
+ $this->connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $this->connection ) );
+
+ $this->store->setConnectionManager( $this->connectionManager );
+
+ $this->jobQueue = $this->getMockBuilder( '\SMW\MediaWiki\JobQueue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'JobQueue', $this->jobQueue );
+
+ InMemoryPoolCache::getInstance()->clear();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ InMemoryPoolCache::getInstance()->clear();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ RedirectStore::class,
+ new RedirectStore( $this->store )
+ );
+ }
+
+ public function testFindRedirectIdForNonCachedRedirect() {
+
+ $row = new \stdClass;
+ $row->o_id = 42;
+
+ $this->connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [
+ 's_title' => 'Foo',
+ 's_namespace' => 0 ] ) )
+ ->will( $this->returnValue( $row ) );
+
+ $instance = new RedirectStore(
+ $this->store
+ );
+
+ $this->assertEquals(
+ 42,
+ $instance->findRedirect( 'Foo', 0 )
+ );
+
+ $stats = InMemoryPoolCache::getInstance()->getStats();
+
+ $this->assertEquals(
+ 0,
+ $stats['sql.store.redirect.infostore']['hits']
+ );
+
+ $instance->findRedirect( 'Foo', 0 );
+
+ $stats = InMemoryPoolCache::getInstance()->getStats();
+
+ $this->assertEquals(
+ 1,
+ $stats['sql.store.redirect.infostore']['hits']
+ );
+ }
+
+ public function testFindRedirectIdForNonCachedNonRedirect() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [
+ 's_title' => 'Foo',
+ 's_namespace' => 0 ] ) )
+ ->will( $this->returnValue( false ) );
+
+ $instance = new RedirectStore(
+ $this->store
+ );
+
+ $this->assertEquals(
+ 0,
+ $instance->findRedirect( 'Foo', 0 )
+ );
+ }
+
+ public function testAddRedirectInfoRecordToFetchFromCache() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'insert' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [
+ 's_title' => 'Foo',
+ 's_namespace' => 0,
+ 'o_id' => 42 ] ) );
+
+ $instance = new RedirectStore(
+ $this->store
+ );
+
+ $instance->addRedirect( 42, 'Foo', 0 );
+
+ $this->assertEquals(
+ 42,
+ $instance->findRedirect( 'Foo', 0 )
+ );
+ }
+
+ public function testDeleteRedirectInfoRecord() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'delete' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [
+ 's_title' => 'Foo',
+ 's_namespace' => 9001 ] ) );
+
+ $instance = new RedirectStore(
+ $this->store
+ );
+
+ $instance->deleteRedirect( 'Foo', 9001 );
+
+ $this->assertEquals(
+ 0,
+ $instance->findRedirect( 'Foo', 9001 )
+ );
+ }
+
+ public function testUpdateRedirect() {
+
+ $row = new \stdClass;
+ $row->ns = NS_MAIN;
+ $row->t = 'Bar';
+
+ $this->connection->expects( $this->once() )
+ ->method( 'select' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'Foo' => 42 ] ) )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $propertyTable = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTable->expects( $this->once() )
+ ->method( 'getFields' )
+ ->will( $this->returnValue( [ 'Foo' => \SMW\SQLStore\TableBuilder\FieldType::FIELD_ID ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->setConnectionManager( $this->connectionManager );
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $propertyTable ] ) );
+
+ $store->setOption(
+ \SMW\Store::OPT_CREATE_UPDATE_JOB,
+ true
+ );
+
+ $this->testEnvironment->addConfiguration(
+ 'smwgEnableUpdateJobs',
+ true
+ );
+
+ $store->setOption(
+ 'smwgEnableUpdateJobs',
+ true
+ );
+
+ $this->jobQueue->expects( $this->once() )
+ ->method( 'push' );
+
+ $instance = new RedirectStore(
+ $store
+ );
+
+ $instance->setEqualitySupportFlag( SMW_EQ_FULL );
+ $instance->updateRedirect( 42, 'Foo', NS_MAIN );
+ }
+
+ public function testUpdateRedirectNotEnabled() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyTables' ] )
+ ->getMock();
+
+ $store->expects( $this->never() )
+ ->method( 'getPropertyTables' );
+
+ $store->setOption(
+ \SMW\Store::OPT_CREATE_UPDATE_JOB,
+ false
+ );
+
+ $instance = new RedirectStore(
+ $store
+ );
+
+ $instance->setEqualitySupportFlag( SMW_EQ_NONE );
+ $instance->updateRedirect( 42, 'Foo', NS_MAIN );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RequestOptionsProcTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RequestOptionsProcTest.php
new file mode 100644
index 00000000..f2abf700
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/RequestOptionsProcTest.php
@@ -0,0 +1,343 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\RequestOptionsProc;
+use SMWRequestOptions as RequestOptions;
+use SMWStringCondition as StringCondition;
+
+/**
+ * @covers \SMW\SQLStore\RequestOptionsProc
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class RequestOptionsProcTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testGetSQLOptions() {
+
+ $requestOptions = new RequestOptions();
+ $requestOptions->limit = 1;
+ $requestOptions->offset = 2;
+ $requestOptions->sort = true;
+
+ $expected = [
+ 'LIMIT' => 1,
+ 'OFFSET' => 2
+ ];
+
+ $this->assertEquals(
+ $expected,
+ RequestOptionsProc::getSQLOptions( $requestOptions, 'Foo' )
+ );
+ }
+
+ public function testGetSQLOptionsWithOrderBy() {
+
+ $instance = new RequestOptionsProc( $this->store );
+
+ $requestOptions = new RequestOptions();
+ $requestOptions->limit = 2;
+ $requestOptions->offset = 2;
+ $requestOptions->sort = true;
+
+ $expected = [
+ 'LIMIT' => 2,
+ 'OFFSET' => 2,
+ 'ORDER BY' => 'Foo'
+ ];
+
+ $this->assertEquals(
+ $expected,
+ RequestOptionsProc::getSQLOptions( $requestOptions, 'Foo' )
+ );
+ }
+
+ /**
+ * @dataProvider requestOptionsToSqlConditionsProvider
+ */
+ public function testGetSQLConditions( $requestOptions, $valueCol, $labelCol, $expected ) {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'addQuotes' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->assertEquals(
+ $expected,
+ RequestOptionsProc::getSQLConditions( $this->store, $requestOptions, $valueCol, $labelCol )
+ );
+ }
+
+ /**
+ * @dataProvider requestOptionsToApplyProvider
+ */
+ public function testApplyRequestOptions( $data, $requestOptions, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ RequestOptionsProc::applyRequestOptions( $this->store, $data, $requestOptions )
+ );
+ }
+
+ public function requestOptionsToSqlConditionsProvider() {
+
+ $provider = [];
+
+ # 0
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ '',
+ ' AND Foo >= 1'
+ ];
+
+ # 1
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foobar', StringCondition::STRCOND_PRE );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' AND Foo >= 1 AND Bar LIKE foobar%'
+ ];
+
+ # 2
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foobar', StringCondition::STRCOND_PRE, true );
+ $requestOptions->addStringCondition( 'foobaz', StringCondition::STRCOND_POST, true );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' AND Foo >= 1 OR Bar LIKE foobar% OR Bar LIKE %foobaz'
+ ];
+
+ # 3
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foo_bar', StringCondition::COND_EQ );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' AND Foo >= 1 AND Bar = foo_bar'
+ ];
+
+ # 4
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foo_bar', StringCondition::COND_EQ );
+ $requestOptions->addExtraCondition( 'abd = 123' );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' AND Foo >= 1 AND Bar = foo_bar AND abd = 123'
+ ];
+
+ # 5
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foo_bar', StringCondition::COND_EQ );
+ $requestOptions->addExtraCondition( [ 'OR' => 'abd = 123' ] );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' AND Foo >= 1 AND Bar = foo_bar OR abd = 123'
+ ];
+
+ # 6
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foo_bar', StringCondition::COND_EQ, true, true );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' ( AND Foo >= 1) AND (Bar NOT = foo_bar) '
+ ];
+
+ # 7
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foo_bar', StringCondition::COND_EQ, true );
+ $requestOptions->addStringCondition( 'foobar', StringCondition::COND_POST, true, true );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' ( AND Foo >= 1 OR Bar = foo_bar) AND (Bar NOT LIKE %foobar) '
+ ];
+
+ # 8
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $requestOptions->addStringCondition( 'foo_bar', StringCondition::COND_EQ, true );
+ $requestOptions->addStringCondition( 'foobar', StringCondition::COND_POST, false, true );
+ $requestOptions->addStringCondition( 'foobar_ex', StringCondition::COND_EQ, false, true );
+
+ $provider[] = [
+ $requestOptions,
+ 'Foo',
+ 'Bar',
+ ' ( ( AND Foo >= 1 OR Bar = foo_bar) AND (Bar NOT LIKE %foobar) ) AND (Bar NOT = foobar_ex) '
+ ];
+
+ return $provider;
+ }
+
+ public function requestOptionsToApplyProvider() {
+
+ $provider = [];
+
+ #0
+ $requestOptions = new RequestOptions();
+ $requestOptions->boundary = true;
+
+ $provider[] = [
+ [
+ new \SMWDIBlob( 'Foo' )
+ ],
+ $requestOptions,
+ [
+ new \SMWDIBlob( 'Foo' )
+ ]
+ ];
+
+ #1
+ $requestOptions = new RequestOptions();
+ $requestOptions->addStringCondition( 'Foo', StringCondition::STRCOND_PRE );
+
+ $provider[] = [
+ [
+ new \SMWDIBlob( 'Foo' )
+ ],
+ $requestOptions,
+ [
+ new \SMWDIBlob( 'Foo' )
+ ]
+ ];
+
+ #2 String not match
+ $requestOptions = new RequestOptions();
+ $requestOptions->addStringCondition( 'Bar', StringCondition::STRCOND_POST );
+
+ $provider[] = [
+ [
+ new \SMWDIBlob( 'Foo' )
+ ],
+ $requestOptions,
+ []
+ ];
+
+ #3 Limit
+ $requestOptions = new RequestOptions();
+ $requestOptions->limit = 1;
+
+ $provider[] = [
+ [
+ new \SMWDIBlob( 'Foo' ),
+ new \SMWDIBlob( 'Bar' )
+ ],
+ $requestOptions,
+ [
+ new \SMWDIBlob( 'Foo' )
+ ]
+ ];
+
+ #4 ascending
+ $requestOptions = new RequestOptions();
+ $requestOptions->sort = true;
+ $requestOptions->ascending = true;
+
+ $provider[] = [
+ [
+ new \SMWDIBlob( 'Foo' ),
+ new \SMWDIBlob( 'Bar' )
+ ],
+ $requestOptions,
+ [
+ new \SMWDIBlob( 'Bar' ),
+ new \SMWDIBlob( 'Foo' )
+ ]
+ ];
+
+ #5 descending
+ $requestOptions = new RequestOptions();
+ $requestOptions->sort = true;
+ $requestOptions->ascending = false;
+
+ $provider[] = [
+ [
+ new \SMWDIBlob( 'Foo' ),
+ new \SMWDIBlob( 'Bar' )
+ ],
+ $requestOptions,
+ [
+ new \SMWDIBlob( 'Foo' ),
+ new \SMWDIBlob( 'Bar' )
+ ]
+ ];
+
+ #6 descending
+ $requestOptions = new RequestOptions();
+ $requestOptions->sort = true;
+ $requestOptions->ascending = false;
+
+ $provider[] = [
+ [
+ new \SMWDINumber( 10 ),
+ new \SMWDINumber( 200 )
+ ],
+ $requestOptions,
+ [
+ new \SMWDINumber( 200 ),
+ new \SMWDINumber( 10 )
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/SQLStoreFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/SQLStoreFactoryTest.php
new file mode 100644
index 00000000..c175c958
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/SQLStoreFactoryTest.php
@@ -0,0 +1,438 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\Options;
+use SMW\SQLStore\SQLStoreFactory;
+use SMW\Tests\TestEnvironment;
+use SMWSQLStore3;
+
+/**
+ * @covers \SMW\SQLStore\SQLStoreFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SQLStoreFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\SQLStoreFactory',
+ new SQLStoreFactory( $this->store )
+ );
+ }
+
+ public function testNewSlaveQueryEngineReturnType() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ '\SMW\QueryEngine',
+ $instance->newSlaveQueryEngine()
+ );
+ }
+
+ public function testNewMasterQueryEngineReturnType() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ '\SMW\QueryEngine',
+ $instance->newMasterQueryEngine()
+ );
+ }
+
+ public function testNewMasterConceptCache() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\ConceptCache',
+ $instance->newMasterConceptCache()
+ );
+ }
+
+ public function testNewSlaveConceptCache() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\ConceptCache',
+ $instance->newSlaveConceptCache()
+ );
+ }
+
+ public function testCanConstractEntityIdManager() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ 'SMWSql3SmwIds',
+ $instance->newEntityTable()
+ );
+ }
+
+ public function testCanConstructUsageStatisticsCachedListLookup() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\Lookup\CachedListLookup',
+ $instance->newUsageStatisticsCachedListLookup()
+ );
+ }
+
+ public function testCanConstructPropertyUsageCachedListLookup() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\Lookup\CachedListLookup',
+ $instance->newPropertyUsageCachedListLookup( null )
+ );
+ }
+
+ public function testCanConstructUnusedPropertyCachedListLookup() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\Lookup\CachedListLookup',
+ $instance->newUnusedPropertyCachedListLookup( null )
+ );
+ }
+
+ public function testCanConstructUndeclaredPropertyCachedListLookup() {
+
+ $instance = new SQLStoreFactory( new SMWSQLStore3() );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\Lookup\CachedListLookup',
+ $instance->newUndeclaredPropertyCachedListLookup( null, '_foo' )
+ );
+ }
+
+ public function testCanConstructCachedListLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $listLookup = $this->getMockBuilder( '\SMW\SQLStore\Lookup\ListLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\Lookup\CachedListLookup',
+ $instance->newCachedListLookup( $listLookup, true, 42 )
+ );
+ }
+
+ public function testCanConstructEntityLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->testEnvironment->addConfiguration( 'smwgEntityLookupCacheType', CACHE_NONE );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\EntityStore\NativeEntityLookup',
+ $instance->newEntityLookup()
+ );
+
+ $this->testEnvironment->addConfiguration( 'smwgEntityLookupCacheType', 'hash' );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\EntityStore\CachingEntityLookup',
+ $instance->newEntityLookup()
+ );
+ }
+
+ public function testCanConstructPropertyTableIdReferenceFinder() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\PropertyTableIdReferenceFinder',
+ $instance->newPropertyTableIdReferenceFinder()
+ );
+ }
+
+ public function testCanConstructDataItemHandlerDispatcher() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\EntityStore\DataItemHandlerDispatcher',
+ $instance->newDataItemHandlerDispatcher()
+ );
+ }
+
+ public function testCanConstructDeferredCachedListLookupUpdate() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ 'SMW\DeferredCallableUpdate',
+ $instance->newDeferredCallableCachedListLookupUpdate()
+ );
+ }
+
+ public function testCanConstructInstaller() {
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new Options() ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SQLStoreFactory( $store );
+
+ $this->assertInstanceOf(
+ 'SMW\SQLStore\Installer',
+ $instance->newInstaller()
+ );
+ }
+
+ public function testGetLogger() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\Psr\Log\LoggerInterface',
+ $instance->getLogger()
+ );
+ }
+
+ public function testCanConstrucTraversalPropertyLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\TraversalPropertyLookup',
+ $instance->newTraversalPropertyLookup()
+ );
+ }
+
+ public function testCanConstrucPropertySubjectsLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\PropertySubjectsLookup',
+ $instance->newPropertySubjectsLookup()
+ );
+ }
+
+ public function testCanConstructPropertyStatisticsStore() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyStatisticsStore',
+ $instance->newPropertyStatisticsStore()
+ );
+ }
+
+ public function testCanConstructIdCacheManager() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $params = [
+ 'entity.id' => '',
+ 'entity.sort' => '',
+ 'entity.lookup' => '',
+ 'table.hash' => ''
+ ];
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\IdCacheManager',
+ $instance->newIdCacheManager( 'foo', $params )
+ );
+ }
+
+ public function testCanConstrucPropertyTableRowDiffer() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\PropertyTableRowDiffer',
+ $instance->newPropertyTableRowDiffer()
+ );
+ }
+
+ public function testCanConstructIdEntityFinder() {
+
+ $idCacheManager = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\IdCacheManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\IdEntityFinder',
+ $instance->newIdEntityFinder( $idCacheManager )
+ );
+ }
+
+ public function testCanConstructIdChanger() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\IdChanger',
+ $instance->newIdChanger()
+ );
+ }
+
+ public function testCanConstructUniquenessLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\UniquenessLookup',
+ $instance->newUniquenessLookup()
+ );
+ }
+
+ public function testCanConstructHierarchyLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\HierarchyLookup',
+ $instance->newHierarchyLookup()
+ );
+ }
+
+ public function testCanConstructSubobjectListFinder() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\SubobjectListFinder',
+ $instance->newSubobjectListFinder()
+ );
+ }
+
+ public function testCanConstructSemanticDataLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityStore\CachingSemanticDataLookup',
+ $instance->newSemanticDataLookup()
+ );
+ }
+
+ public function testCanConstructTableFieldUpdater() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\TableFieldUpdater',
+ $instance->newTableFieldUpdater()
+ );
+ }
+
+ public function testCanConstructRedirectStore() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\RedirectStore',
+ $instance->newRedirectStore()
+ );
+ }
+
+ public function testCanConstructChangePropListener() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\ChangePropListener',
+ $instance->newChangePropListener()
+ );
+ }
+
+ public function testCanConstructChangeOp() {
+
+ $subject = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\ChangeOp\ChangeOp',
+ $instance->newChangeOp( $subject )
+ );
+ }
+
+ public function testCanConstructProximityPropertyValueLookup() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\Lookup\ProximityPropertyValueLookup',
+ $instance->newProximityPropertyValueLookup()
+ );
+ }
+
+ public function testCanConstructEntityValueUniquenessConstraintChecker() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\EntityValueUniquenessConstraintChecker',
+ $instance->newEntityValueUniquenessConstraintChecker()
+ );
+ }
+
+ public function testCanConstructServicesContainer() {
+
+ $instance = new SQLStoreFactory( $this->store );
+
+ $this->assertInstanceOf(
+ '\SMW\Services\ServicesContainer',
+ $instance->newServicesContainer()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/Examiner/HashFieldTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/Examiner/HashFieldTest.php
new file mode 100644
index 00000000..3497f40f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/Examiner/HashFieldTest.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder\Examiner;
+
+use SMW\SQLStore\TableBuilder\Examiner\HashField;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\Examiner\HashField
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.1
+ *
+ * @author mwjames
+ */
+class HashFieldTest extends \PHPUnit_Framework_TestCase {
+
+ private $spyMessageReporter;
+ private $store;
+ private $populateHashField;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->spyMessageReporter = TestEnvironment::getUtilityFactory()->newSpyMessageReporter();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->populateHashField = $this->getMockBuilder( '\SMW\Maintenance\PopulateHashField' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ HashField::class,
+ new HashField( $this->store )
+ );
+ }
+
+ public function testCheck_Populate() {
+
+ $resultWrapper = $this->getMockBuilder( '\ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resultWrapper->expects( $this->once() )
+ ->method( 'numRows' )
+ ->will( $this->returnValue( HashField::threshold() - 1 ) );
+
+ $this->populateHashField->expects( $this->atLeastOnce() )
+ ->method( 'populate' );
+
+ $this->populateHashField->expects( $this->once() )
+ ->method( 'fetchRows' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $instance = new HashField(
+ $this->store,
+ $this->populateHashField
+ );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->check();
+
+ $this->assertContains(
+ 'Checking smw_hash field consistency',
+ $this->spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testCheck_Incomplete() {
+
+ $resultWrapper = $this->getMockBuilder( '\ResultWrapper' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resultWrapper->expects( $this->once() )
+ ->method( 'numRows' )
+ ->will( $this->returnValue( HashField::threshold() + 1 ) );
+
+ $this->populateHashField->expects( $this->atLeastOnce() )
+ ->method( 'setComplete' );
+
+ $this->populateHashField->expects( $this->once() )
+ ->method( 'fetchRows' )
+ ->will( $this->returnValue( $resultWrapper ) );
+
+ $instance = new HashField(
+ $this->store,
+ $this->populateHashField
+ );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->check();
+
+ $this->assertContains(
+ 'Checking smw_hash field consistency',
+ $this->spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/FieldTypeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/FieldTypeTest.php
new file mode 100644
index 00000000..c32616d4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/FieldTypeTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder;
+
+use SMW\SQLStore\TableBuilder\FieldType;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\FieldType
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class FieldTypeTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider fieldTypeProvider
+ */
+ public function testMapType( $fieldType, $fieldTypes, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ FieldType::mapType( $fieldType, $fieldTypes )
+ );
+ }
+
+ public function fieldTypeProvider() {
+
+ $fieldTypes = [
+ 'double' => 'DOUBLE'
+ ];
+
+ $provider[] = [
+ FieldType::TYPE_DOUBLE,
+ $fieldTypes,
+ 'DOUBLE'
+ ];
+
+ $provider[] = [
+ [ FieldType::TYPE_DOUBLE ],
+ $fieldTypes,
+ 'DOUBLE'
+ ];
+
+ $provider[] = [
+ [ FieldType::TYPE_DOUBLE, 'NOT NULL' ],
+ $fieldTypes,
+ 'DOUBLE NOT NULL'
+ ];
+
+ $provider[] = [
+ [ FieldType::TYPE_DOUBLE, 'NOT NULL', 'thirdParameterIsNeglected' ],
+ $fieldTypes,
+ 'DOUBLE NOT NULL'
+ ];
+
+ $provider[] = [
+ [ 'notMatchableTypeThereforeReturnAsIs' ],
+ $fieldTypes,
+ 'notMatchableTypeThereforeReturnAsIs'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/MySQLTableBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/MySQLTableBuilderTest.php
new file mode 100644
index 00000000..4babb85b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/MySQLTableBuilderTest.php
@@ -0,0 +1,396 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder;
+
+use SMW\SQLStore\TableBuilder\MySQLTableBuilder;
+use SMW\SQLStore\TableBuilder\Table;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\MySQLTableBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class MySQLTableBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query', 'dbSchema', 'tablePrefix' ] )
+ ->getMockForAbstractClass();
+
+ $this->connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'dbSchema' )
+ ->will( $this->returnValue( '' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tablePrefix' )
+ ->will( $this->returnValue( '' ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ MySQLTableBuilder::class,
+ MySQLTableBuilder::factory( $this->connection )
+ );
+ }
+
+ public function testCreateNewTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->equalTo( 'CREATE TABLE `xyz`."foo" (bar TEXT) tableoptions_foobar' ) );
+
+ $instance = MySQLTableBuilder::factory( $connection );
+ $instance->addConfig( 'wgDBname', 'xyz' );
+ $instance->addConfig( 'wgDBTableOptions', 'tableoptions_foobar' );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateNewTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE TABLE `xyz`."foo"' ) );
+
+ $instance = MySQLTableBuilder::factory( $this->connection );
+ $instance->addConfig( 'wgDBname', 'xyz' );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateExistingTableWithNewField() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $connection->expects( $this->at( 2 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DESCRIBE' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text FIRST' ) );
+
+ $instance = MySQLTableBuilder::factory( $connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateExistingTableWithNewField_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DESCRIBE' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 5 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text FIRST' ) );
+
+ $instance = MySQLTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateExistingTableWithNewFieldAndDefault() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $connection->expects( $this->at( 2 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DESCRIBE' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text' . " DEFAULT '0'" . ' FIRST' ) );
+
+ $instance = MySQLTableBuilder::factory( $connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addDefault( 'bar', 0 );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateExistingTableWithNewFieldAndDefault_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DESCRIBE' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 5 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text' . " DEFAULT '0'" . ' FIRST' ) );
+
+ $instance = MySQLTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addDefault( 'bar', 0 );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateIndex() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SHOW INDEX' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD INDEX (bar)' ) );
+
+ $instance = MySQLTableBuilder::factory( $connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addIndex( 'bar' );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateIndex_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->at( 7 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SHOW INDEX' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 10 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD INDEX (bar)' ) );
+
+ $instance = MySQLTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addIndex( 'bar' );
+
+ $instance->create( $table );
+ }
+
+ public function testDropTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DROP TABLE "foo"' ) );
+
+ $instance = MySQLTableBuilder::factory( $connection );
+
+ $table = new Table( 'foo' );
+ $instance->drop( $table );
+ }
+
+ public function testDropTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DROP TABLE "foo"' ) );
+
+ $instance = MySQLTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->drop( $table );
+ }
+
+ public function testOptimizeTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'query' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $connection->expects( $this->at( 1 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ANALYZE TABLE "foo"' ) );
+
+ $connection->expects( $this->at( 2 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'OPTIMIZE TABLE "foo"' ) );
+
+ $instance = MySQLTableBuilder::factory( $connection );
+
+ $table = new Table( 'foo' );
+ $instance->optimize( $table );
+ }
+
+ public function testOptimizeTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ANALYZE TABLE "foo"' ) );
+
+ $this->connection->expects( $this->at( 6 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'OPTIMIZE TABLE "foo"' ) );
+
+ $instance = MySQLTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->optimize( $table );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/PostgresTableBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/PostgresTableBuilderTest.php
new file mode 100644
index 00000000..9211a2d3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/PostgresTableBuilderTest.php
@@ -0,0 +1,385 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder;
+
+use SMW\SQLStore\TableBuilder\PostgresTableBuilder;
+use SMW\SQLStore\TableBuilder\Table;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\PostgresTableBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class PostgresTableBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query', 'dbSchema', 'tablePrefix', 'onTransactionIdle' ] )
+ ->getMockForAbstractClass();
+
+ $this->connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'postgres' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'dbSchema' )
+ ->will( $this->returnValue( '' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tablePrefix' )
+ ->will( $this->returnValue( '' ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ PostgresTableBuilder::class,
+ PostgresTableBuilder::factory( $this->connection )
+ );
+ }
+
+ public function testCreateTableOnNewTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE TABLE' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateTableOnNewTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE TABLE' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewField() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 2 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SELECT a.attname as' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD "bar" TEXT' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewField_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SELECT a.attname as' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 5 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD "bar" TEXT' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewFieldAndDefault() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 2 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SELECT a.attname as' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD "bar" TEXT'. " DEFAULT '0'" ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addDefault( 'bar', 0 );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewFieldAndDefault_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SELECT a.attname as' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 5 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD "bar" TEXT'. " DEFAULT '0'" ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addDefault( 'bar', 0 );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateIndex() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'indexInfo' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SELECT i.relname AS indexname' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 5 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE INDEX foo_idx_bar ON foo (bar)' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addIndex( 'bar' );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateIndex_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'indexInfo' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->at( 7 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'SELECT i.relname AS indexname' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 11 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE INDEX foo_idx_bar ON foo (bar)' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addIndex( 'bar' );
+
+ $instance->create( $table );
+ }
+
+ public function testDropTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DROP TABLE IF EXISTS "foo"' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->drop( $table );
+ }
+
+ public function testDropTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DROP TABLE IF EXISTS "foo"' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->drop( $table );
+ }
+
+ public function testDoCheckOnAfterCreate() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) { return $callback(); } ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER SEQUENCE' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $instance->checkOn( $instance::POST_CREATION );
+ }
+
+ public function testDoCheckOnAfterCreate_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'onTransactionIdle' )
+ ->will( $this->returnCallback( function( $callback ) { return $callback(); } ) );
+
+ $this->connection->expects( $this->at( 6 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER SEQUENCE' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $instance->checkOn( $instance::POST_CREATION );
+ }
+
+ public function testOptimizeTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'postgres' ) );
+
+ $this->connection->expects( $this->at( 1 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ANALYZE "foo"' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->optimize( $table );
+ }
+
+ public function testOptimizeTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'postgres' ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ANALYZE "foo"' ) );
+
+ $instance = PostgresTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->optimize( $table );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/SQLiteTableBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/SQLiteTableBuilderTest.php
new file mode 100644
index 00000000..05d31825
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/SQLiteTableBuilderTest.php
@@ -0,0 +1,331 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder;
+
+use SMW\SQLStore\TableBuilder\SQLiteTableBuilder;
+use SMW\SQLStore\TableBuilder\Table;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\SQLiteTableBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SQLiteTableBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+
+ protected function setUp() {
+
+ $this->connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'tableExists', 'query', 'dbSchema', 'tablePrefix' ] )
+ ->getMockForAbstractClass();
+
+ $this->connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'sqlite' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'dbSchema' )
+ ->will( $this->returnValue( '' ) );
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tablePrefix' )
+ ->will( $this->returnValue( '' ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SQLiteTableBuilder::class,
+ SQLiteTableBuilder::factory( $this->connection )
+ );
+ }
+
+ public function testCreateTableOnNewTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE TABLE' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateTableOnNewTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE TABLE' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewField() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 2 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'PRAGMA table_info("foo")' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewField_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'PRAGMA table_info("foo")' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 5 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewFieldAndDefault() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 2 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'PRAGMA table_info("foo")' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text' . " DEFAULT '0'" ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addDefault( 'bar', 0 );
+
+ $instance->create( $table );
+ }
+
+ public function testUpdateTableWithNewFieldAndDefault_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'PRAGMA table_info("foo")' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 5 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ALTER TABLE "foo" ADD `bar` text' . " DEFAULT '0'" ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addDefault( 'bar', 0 );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateIndex() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'PRAGMA index_list("foo")' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 4 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE INDEX "foo"_index0' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addIndex( 'bar' );
+
+ $instance->create( $table );
+ }
+
+ public function testCreateIndex_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->any() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( false ) );
+
+ $this->connection->expects( $this->at( 7 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'PRAGMA index_list("foo")' ) )
+ ->will( $this->returnValue( [] ) );
+
+ $this->connection->expects( $this->at( 10 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'CREATE INDEX "foo"_index0' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $table->addColumn( 'bar', 'text' );
+ $table->addIndex( 'bar' );
+
+ $instance->create( $table );
+ }
+
+ public function testDropTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DROP TABLE "foo"' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->drop( $table );
+ }
+
+ public function testDropTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->once() )
+ ->method( 'tableExists' )
+ ->will( $this->returnValue( true ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'DROP TABLE "foo"' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->drop( $table );
+ }
+
+ public function testOptimizeTable() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '>=' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->at( 1 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ANALYZE "foo"' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->optimize( $table );
+ }
+
+ public function testOptimizeTable_132() {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.32', '<' ) ) {
+ $this->markTestSkipped( 'MediaWiki changed the Database signature!' );
+ }
+
+ $this->connection->expects( $this->at( 3 ) )
+ ->method( 'query' )
+ ->with( $this->stringContains( 'ANALYZE "foo"' ) );
+
+ $instance = SQLiteTableBuilder::factory( $this->connection );
+
+ $table = new Table( 'foo' );
+ $instance->optimize( $table );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableBuilderTest.php
new file mode 100644
index 00000000..edcdbda7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableBuilderTest.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder;
+
+use SMW\SQLStore\TableBuilder\TableBuilder;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\TableBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TableBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstructForMySQL() {
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'mysql' ) );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\TableBuilder\MySQLTableBuilder',
+ TableBuilder::factory( $connection )
+ );
+ }
+
+ public function testCanConstructForSQLite() {
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'sqlite' ) );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\TableBuilder\SQLiteTableBuilder',
+ TableBuilder::factory( $connection )
+ );
+ }
+
+ public function testCanConstructForPostgres() {
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'postgres' ) );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\TableBuilder\PostgresTableBuilder',
+ TableBuilder::factory( $connection )
+ );
+ }
+
+ public function testTryToConstructOnInvalidTypeThrowsException() {
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->any() )
+ ->method( 'getType' )
+ ->will( $this->returnValue( 'foo' ) );
+
+ $this->setExpectedException( 'RuntimeException' );
+ TableBuilder::factory( $connection );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableTest.php
new file mode 100644
index 00000000..275fdc55
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TableTest.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder;
+
+use SMW\SQLStore\TableBuilder\Table;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\Table
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TableTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Table::class,
+ new Table( 'Foo' )
+ );
+ }
+
+ public function testAddColumn() {
+
+ $instance = new Table( 'Foo' );
+
+ $instance->addColumn( 'b', 'integer' );
+
+ $expected = [
+ 'fields' => [
+ 'b' => 'integer'
+ ]
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getAttributes()
+ );
+ }
+
+ public function testAddIndex() {
+
+ $instance = new Table( 'Foo' );
+
+ $instance->addIndex( 'bar' );
+
+ $expected = [
+ 'indices' => [
+ 'bar'
+ ]
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getAttributes()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHash()
+ );
+ }
+
+ public function testAddIndexWithKey() {
+
+ $instance = new Table( 'Foo' );
+
+ $instance->addIndex( [ 'foobar' ], 'bar' );
+
+ $expected = [
+ 'indices' => [
+ 'bar' => [ 'foobar' ]
+ ]
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getAttributes()
+ );
+ }
+
+ public function testAddOption() {
+
+ $instance = new Table( 'Foo' );
+
+ $instance->addOption( 'bar', [ 'foobar' ] );
+
+ $expected = [
+ 'bar' => [ 'foobar' ]
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $instance->getAttributes()
+ );
+
+ $this->assertEquals(
+ [ 'foobar' ],
+ $instance->get( 'bar' )
+ );
+ }
+
+ public function testGetOnUnregsiteredKeyThrowsException() {
+
+ $instance = new Table( 'Foo' );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->get( 'bar' );
+ }
+
+ /**
+ * @dataProvider invalidOptionsProvider
+ */
+ public function testAddOptionOnReservedOptionKeyThrowsException( $key ) {
+
+ $instance = new Table( 'Foo' );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $instance->addOption( $key, [] );
+ }
+
+ public function invalidOptionsProvider() {
+
+ $provider[] = [
+ 'fields'
+ ];
+
+ $provider[] = [
+ 'indices'
+ ];
+
+ $provider[] = [
+ 'defaults'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TemporaryTableBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TemporaryTableBuilderTest.php
new file mode 100644
index 00000000..826fd685
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableBuilder/TemporaryTableBuilderTest.php
@@ -0,0 +1,134 @@
+<?php
+
+namespace SMW\Tests\SQLStore\TableBuilder;
+
+use SMW\MediaWiki\Database;
+use SMW\SQLStore\TableBuilder\TemporaryTableBuilder;
+
+/**
+ * @covers \SMW\SQLStore\TableBuilder\TemporaryTableBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TemporaryTableBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ private $connection;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TemporaryTableBuilder::class,
+ new TemporaryTableBuilder( $this->connection )
+ );
+ }
+
+ public function testCreateWithoutAutoCommit() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' );
+
+ $instance = new TemporaryTableBuilder(
+ $this->connection
+ );
+
+ $instance->create( 'Foo' );
+ }
+
+ public function testCreateWithoutAutoCommitOnPostgres() {
+
+ $this->connection->expects( $this->never() )
+ ->method( 'setFlag' );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->anything() );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'isType' )
+ ->with( $this->equalTo( 'postgres' ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new TemporaryTableBuilder(
+ $this->connection
+ );
+
+ $instance->create( 'Foo' );
+ }
+
+ public function testCreateWithAutoCommitFlag() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'setFlag' )
+ ->with( $this->equalTo( Database::AUTO_COMMIT ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->anything() );
+
+ $instance = new TemporaryTableBuilder(
+ $this->connection
+ );
+
+ $instance->setAutoCommitFlag( true );
+ $instance->create( 'Foo' );
+ }
+
+ public function testDropWithoutAutoCommit() {
+
+ $this->connection->expects( $this->never() )
+ ->method( 'setFlag' );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->anything() );
+
+ $instance = new TemporaryTableBuilder(
+ $this->connection
+ );
+
+ $instance->drop( 'Foo' );
+ }
+
+ public function testDropWithAutoCommitFlag() {
+
+ $this->connection->expects( $this->once() )
+ ->method( 'setFlag' )
+ ->with( $this->equalTo( Database::AUTO_COMMIT ) );
+
+ $this->connection->expects( $this->once() )
+ ->method( 'query' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->anything() );
+
+ $instance = new TemporaryTableBuilder(
+ $this->connection
+ );
+
+ $instance->setAutoCommitFlag( true );
+ $instance->drop( 'Foo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableFieldUpdaterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableFieldUpdaterTest.php
new file mode 100644
index 00000000..07ed3df5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableFieldUpdaterTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\TableFieldUpdater;
+
+/**
+ * @covers \SMW\SQLStore\TableFieldUpdater
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TableFieldUpdaterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ TableFieldUpdater::class,
+ new TableFieldUpdater( $store )
+ );
+ }
+
+ public function testUpdateSortField() {
+
+ $collator = $this->getMockBuilder( '\SMW\MediaWiki\Collator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $collator->expects( $this->once() )
+ ->method( 'getSortKey' );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [ 'smw_id' => 42 ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new TableFieldUpdater(
+ $store,
+ $collator
+ );
+
+ $instance->updateSortField( 42, 'Foo' );
+ }
+
+ public function testUpdateRevField() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [ 'smw_rev' => 1001 ] ),
+ $this->equalTo( [ 'smw_id' => 42 ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new TableFieldUpdater(
+ $store
+ );
+
+ $instance->updateRevField( 42, 1001 );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableIntegrityExaminerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableIntegrityExaminerTest.php
new file mode 100644
index 00000000..1c9b561f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableIntegrityExaminerTest.php
@@ -0,0 +1,329 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\Tests\TestEnvironment;
+use SMW\SQLStore\TableIntegrityExaminer;
+
+/**
+ * @covers \SMW\SQLStore\TableIntegrityExaminer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TableIntegrityExaminerTest extends \PHPUnit_Framework_TestCase {
+
+ private $spyMessageReporter;
+ private $hashField;
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->spyMessageReporter = TestEnvironment::getUtilityFactory()->newSpyMessageReporter();
+
+ $this->hashField = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder\Examiner\HashField' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ TableIntegrityExaminer::class,
+ new TableIntegrityExaminer( $this->store, $this->hashField )
+ );
+ }
+
+ public function testCheckOnPostCreationOnValidProperty() {
+
+ $row = [
+ 'smw_id' => 42,
+ 'smw_iw' => '',
+ 'smw_proptable_hash' => '',
+ 'smw_hash' => ''
+ ];
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getPropertyInterwiki', 'moveSMWPageID', 'getPropertyTableHashes' ] )
+ ->getMock();
+
+ $idTable->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyInterwiki' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( (object)$row ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'replace' );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'checkOn' );
+
+ $instance = new TableIntegrityExaminer(
+ $store,
+ $this->hashField
+ );
+
+ $instance->setPredefinedPropertyList( [
+ 'Foo' => 42
+ ] );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->checkOnPostCreation( $tableBuilder );
+ }
+
+ public function testCheckOnPostCreationOnValidProperty_NotFixed() {
+
+ $row = [
+ 'smw_id' => 42,
+ 'smw_iw' => '',
+ 'smw_proptable_hash' => '',
+ 'smw_hash' => ''
+ ];
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'moveSMWPageID', 'getPropertyInterwiki' ] )
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->at( 1 ) )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( (object)[ 'smw_id' => \SMW\SQLStore\SQLStore::FIXED_PROPERTY_ID_UPPERBOUND ] ) );
+
+ $connection->expects( $this->at( 2 ) )
+ ->method( 'selectRow' )
+ ->with(
+ $this->anything(),
+ $this->anything(),
+ $this->equalTo( [
+ 'smw_title' => 'Foo',
+ 'smw_namespace' => SMW_NS_PROPERTY,
+ 'smw_subobject' => '' ] ) )
+ ->will( $this->returnValue( (object)$row ) );
+
+ $connection->expects( $this->at( 3 ) )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( (object)$row ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'checkOn' );
+
+ $instance = new TableIntegrityExaminer(
+ $store,
+ $this->hashField
+ );
+
+ $instance->setPredefinedPropertyList( [
+ 'Foo' => null
+ ] );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->checkOnPostCreation( $tableBuilder );
+ }
+
+ public function testCheckOnPostCreationOnInvalidProperty() {
+
+ $row = new \stdClass;
+ $row->smw_id = 42;
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'getPropertyInterwiki', 'moveSMWPageID' ] )
+ ->getMock();
+
+ $idTable->expects( $this->never() )
+ ->method( 'getPropertyInterwiki' );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( $row ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getObjectIds', 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'checkOn' );
+
+ $instance = new TableIntegrityExaminer(
+ $store,
+ $this->hashField
+ );
+
+ $instance->setPredefinedPropertyList( [
+ '_FOO' => 42
+ ] );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->checkOnPostCreation( $tableBuilder );
+
+ $this->assertContains(
+ 'invalid registration',
+ $this->spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testCheckOnActivitiesPostCreationForID_TABLE() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( false ) );
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'tableName' )
+ ->will( $this->returnValue( 'smw_object_ids' ) );
+
+ $idTable = $this->getMockBuilder( '\stdClass' )
+ ->setMethods( [ 'moveSMWPageID' ] )
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection', 'getObjectIds' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableBuilder->expects( $this->any() )
+ ->method( 'getLog' )
+ ->will( $this->returnValue( [ 'smw_object_ids' => [ 'smw_sort' => 'field.new' ] ] ) );
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'checkOn' );
+
+ $instance = new TableIntegrityExaminer(
+ $store,
+ $this->hashField
+ );
+
+ $instance->setPredefinedPropertyList( [] );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->checkOnPostCreation( $tableBuilder );
+
+ $this->assertContains(
+ 'copying smw_sortkey to smw_sort',
+ $this->spyMessageReporter->getMessagesAsString()
+ );
+ }
+
+ public function testCheckOnPostDestruction() {
+
+ $connection = $this->getMockBuilder( '\DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'listTables' ] )
+ ->getMockForAbstractClass();
+
+ $connection->expects( $this->atLeastOnce() )
+ ->method( 'listTables' )
+ ->will( $this->returnValue( [ 'abcsmw_foo' ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getConnection' ] )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $tableBuilder = $this->getMockBuilder( '\SMW\SQLStore\TableBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'checkOn' );
+
+ $tableBuilder->expects( $this->once() )
+ ->method( 'drop' );
+
+ $instance = new TableIntegrityExaminer(
+ $store,
+ $this->hashField
+ );
+
+ $instance->setMessageReporter( $this->spyMessageReporter );
+ $instance->checkOnPostDestruction( $tableBuilder );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableSchemaManagerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableSchemaManagerTest.php
new file mode 100644
index 00000000..5b795a11
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SQLStore/TableSchemaManagerTest.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use SMW\SQLStore\TableBuilder\FieldType;
+use SMW\SQLStore\TableSchemaManager;
+
+/**
+ * @covers \SMW\SQLStore\TableSchemaManager
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TableSchemaManagerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ TableSchemaManager::class,
+ new TableSchemaManager( $store )
+ );
+ }
+
+ public function testGetTablesWithEmptyPropertyTableDefinition() {
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->once() )
+ ->method( 'getTableFields' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $propertyTableDefinition ] ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $instance = new TableSchemaManager(
+ $store
+ );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getTables()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHash()
+ );
+ }
+
+ public function testFindTableDefinitionWithNoCaseFeature() {
+
+ $propertyTableDefinition = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataItemHandler = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\DataItemHandler' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItemHandler->expects( $this->once() )
+ ->method( 'getTableFields' )
+ ->will( $this->returnValue( [] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->once() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [ $propertyTableDefinition ] ) );
+
+ $store->expects( $this->once() )
+ ->method( 'getDataItemHandlerForDIType' )
+ ->will( $this->returnValue( $dataItemHandler ) );
+
+ $instance = new TableSchemaManager(
+ $store
+ );
+
+ $instance->setFeatureFlags(
+ SMW_FIELDT_CHAR_NOCASE
+ );
+
+ $table = $instance->findTable( \SMW\SQLStore\SQLStore::ID_TABLE );
+ $fields = $table->get( 'fields' );
+
+ $this->assertContains(
+ FieldType::TYPE_CHAR_NOCASE,
+ $fields['smw_sortkey']
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentFormatterTest.php
new file mode 100644
index 00000000..e3adaad7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentFormatterTest.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests\Schema\Content;
+
+use SMW\Schema\Content\ContentFormatter;
+use SMW\Schema\Schema;
+
+/**
+ * @covers \SMW\Schema\Content\ContentFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ContentFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ ContentFormatter::class,
+ new ContentFormatter()
+ );
+ }
+
+ public function testGetHelpLink() {
+
+ $schema = $this->getMockBuilder( '\SMW\Schema\Schema' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ContentFormatter();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHelpLink( $schema )
+ );
+ }
+
+ public function testGetText() {
+
+ $schema = $this->getMockBuilder( '\SMW\Schema\Schema' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $schema->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnCallback( [ $this, 'schema_get' ] ) );
+
+ $text = '...';
+ $isYaml = false;
+ $errors = [];
+
+ $instance = new ContentFormatter();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getText( $text, $isYaml, $schema, $errors )
+ );
+ }
+
+ public function testGetText_Errors() {
+
+ $schema = $this->getMockBuilder( '\SMW\Schema\Schema' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $schema->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnCallback( [ $this, 'schema_get' ] ) );
+
+ $text = '...';
+ $isYaml = false;
+
+ $errors = [
+ [ 'property' => 'foo', 'message' => '---' ]
+ ];
+
+ $instance = new ContentFormatter();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getText( $text, $isYaml, $schema, $errors )
+ );
+ }
+
+ public function schema_get( $key ) {
+ return $key === Schema::SCHEMA_TAG ? [] : '';
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentHandlerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentHandlerTest.php
new file mode 100644
index 00000000..3948443b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentHandlerTest.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace SMW\Tests\Schema\Content;
+
+use SMW\Schema\Content\ContentHandler;
+
+/**
+ * @covers \SMW\Schema\Content\ContentHandler
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ContentHandlerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ '\JsonContentHandler',
+ new ContentHandler()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentTest.php
new file mode 100644
index 00000000..65acd635
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/ContentTest.php
@@ -0,0 +1,183 @@
+<?php
+
+namespace SMW\Tests\Schema\Content;
+
+use SMW\Schema\Content\Content;
+
+/**
+ * @covers \SMW\Schema\Content\Content
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ContentTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ '\JsonContent',
+ new Content( 'foo' )
+ );
+ }
+
+ public function testToJson() {
+
+ $text = json_encode( [ 'Foo' => 42 ] );
+
+ $instance = new Content( $text );
+
+ $this->assertEquals(
+ $text,
+ $instance->toJson()
+ );
+ }
+
+ public function testIsYaml() {
+
+ if ( !class_exists( '\Symfony\Component\Yaml\Yaml' ) ) {
+ $this->markTestSkipped( 'Skipping because `Symfony\Component\Yaml\Yaml` is not available!' );
+ }
+
+ $text = json_encode( [ 'Foo' => 42 ] );
+
+ $instance = new Content( $text );
+
+ $this->assertFalse(
+ $instance->isYaml()
+ );
+ }
+
+ public function testPreSaveTransform() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user = $this->getMockBuilder( '\User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new Content(
+ json_encode( [ 'Foo' => 42 ] )
+ );
+
+ $this->assertInstanceof(
+ Content::class,
+ $instance->preSaveTransform( $title, $user, $parserOptions )
+ );
+ }
+
+ public function testFillParserOutput() {
+
+ $schemaDefinition = $this->getMockBuilder( '\SMW\Schema\SchemaDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $schemaValidator = $this->getMockBuilder( '\SMW\Schema\SchemaValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $schemaValidator->expects( $this->any() )
+ ->method( 'validate' )
+ ->will( $this->returnValue( [] ) );
+
+ $schemaFactory = $this->getMockBuilder( '\SMW\Schema\SchemaFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $schemaFactory->expects( $this->any() )
+ ->method( 'newSchema' )
+ ->will( $this->returnValue( $schemaDefinition ) );
+
+ $schemaFactory->expects( $this->any() )
+ ->method( 'newSchemaValidator' )
+ ->will( $this->returnValue( $schemaValidator ) );
+
+ $contentFormatter = $this->getMockBuilder( '\SMW\Schema\Content\ContentFormatter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_SCHEMA ) );
+
+ $parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'setText' );
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'setIndicator' );
+
+ $instance = new Content(
+ json_encode( [ 'Foo' => 42 ] )
+ );
+
+ $instance->setServices( $schemaFactory, $contentFormatter );
+
+ $generateHtml = true;
+ $revId = 42;
+
+ $instance->fillParserOutput( $title, $revId, $parserOptions, $generateHtml, $parserOutput );
+ }
+
+ public function testFillParserOutput_SchemaTypeNotFoundException() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBKey' )
+ ->will( $this->returnValue( 'Foo' ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( SMW_NS_SCHEMA ) );
+
+ $parserOptions = $this->getMockBuilder( '\ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput = $this->getMockBuilder( '\ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOutput->expects( $this->once() )
+ ->method( 'setText' );
+
+ $parserOutput->expects( $this->never() )
+ ->method( 'setIndicator' );
+
+ $instance = new Content(
+ json_encode( [ 'Foo' => 42 ] )
+ );
+
+ $generateHtml = true;
+ $revId = 42;
+
+ $instance->fillParserOutput( $title, $revId, $parserOptions, $generateHtml, $parserOutput );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/HtmlBuilderTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/HtmlBuilderTest.php
new file mode 100644
index 00000000..ef9706e1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Content/HtmlBuilderTest.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace SMW\Tests\Schema\Content;
+
+use SMW\Schema\Content\HtmlBuilder;
+use SMW\Schema\Schema;
+
+/**
+ * @covers \SMW\Schema\Content\HtmlBuilder
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlBuilderTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceof(
+ HtmlBuilder::class,
+ new HtmlBuilder()
+ );
+ }
+
+ /**
+ * @dataProvider buildParamsProvider
+ */
+ public function testBuild( $key, $params ) {
+
+ $instance = new HtmlBuilder();
+
+ $this->assertInternalType(
+ 'string',
+ $instance->build( $key, $params )
+ );
+ }
+
+ public function buildParamsProvider() {
+
+ yield [
+ 'schema_head',
+ [
+ 'link' => 'Foo',
+ 'description' => 'bar',
+ 'schema-title' => '...',
+ 'error' => 'err---rr',
+ 'error-title' => 'error'
+ ]
+ ];
+
+ yield [
+ 'schema_body',
+ [
+ 'text' => 'Foo',
+ 'unknown_type' => 'bar'
+ ]
+ ];
+
+ yield [
+ 'schema_error_text',
+ [
+ 'list' => [],
+ 'schema' => 'Foo'
+ ]
+ ];
+
+ yield [
+ 'schema_error',
+ [
+ 'text' => '...',
+ 'msg' => 'Foo'
+ ]
+ ];
+
+ yield [
+ 'schema_footer',
+ [
+ 'href_type' => '...',
+ 'link_type' => 'Foo',
+ 'msg_type' => 'Bar',
+ 'tags' => [],
+ 'href_tag' => 'Foobar'
+ ]
+ ];
+
+ yield [
+ 'schema_unknown_type',
+ [
+ 'msg' => 'Foo'
+ ]
+ ];
+
+ yield [
+ 'schema_help_link',
+ [
+ 'href' => 'Foo'
+ ]
+ ];
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaConstructionFailedExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaConstructionFailedExceptionTest.php
new file mode 100644
index 00000000..fd38438d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaConstructionFailedExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Schema\Exception;
+
+use SMW\Schema\Exception\SchemaConstructionFailedException;
+
+/**
+ * @covers \SMW\Schema\Exception\SchemaConstructionFailedException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SchemaConstructionFailedExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new SchemaConstructionFailedException( 'foo' );
+
+ $this->assertInstanceof(
+ SchemaConstructionFailedException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaTypeNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaTypeNotFoundExceptionTest.php
new file mode 100644
index 00000000..5be5da8a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/Exception/SchemaTypeNotFoundExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Schema\Exception;
+
+use SMW\Schema\Exception\SchemaTypeNotFoundException;
+
+/**
+ * @covers \SMW\Schema\Exception\SchemaTypeNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SchemaTypeNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new SchemaTypeNotFoundException( 'foo' );
+
+ $this->assertInstanceof(
+ SchemaTypeNotFoundException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\RuntimeException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaDefinitionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaDefinitionTest.php
new file mode 100644
index 00000000..3e20208c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaDefinitionTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests\Schema;
+
+use SMW\Schema\SchemaDefinition;
+
+/**
+ * @covers \SMW\Schema\SchemaDefinition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SchemaDefinitionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new SchemaDefinition( 'foo', [] );
+
+ $this->assertInstanceof(
+ SchemaDefinition::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\SMW\Schema\Schema',
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\JsonSerializable',
+ $instance
+ );
+ }
+
+ public function testGetName() {
+
+ $instance = new SchemaDefinition(
+ 'foo',
+ []
+ );
+
+ $this->assertEquals(
+ 'foo',
+ $instance->getName()
+ );
+ }
+
+ public function testGetSchemaLink() {
+
+ $instance = new SchemaDefinition(
+ 'foo',
+ [],
+ 'BAR'
+ );
+
+ $this->assertEquals(
+ 'BAR',
+ $instance->getValidationSchema()
+ );
+ }
+
+ public function testGet() {
+
+ $def = [
+ 'type' => 'foo_bar',
+ 'description' => 'bar foo bar',
+ 'Schema' => [
+ 'if' => [
+ 'doSomething',
+ 'and' => [
+ 'doSomethingElse'
+ ]
+ ],
+ 'then' => [
+ ]
+ ]
+ ];
+
+ $instance = new SchemaDefinition(
+ 'foo',
+ $def
+ );
+
+ $this->assertEquals(
+ 'foo_bar',
+ $instance->get( SchemaDefinition::SCHEMA_TYPE )
+ );
+
+ $this->assertEquals(
+ [ 'doSomething', 'and' => [ 'doSomethingElse' ] ],
+ $instance->get( 'Schema.if' )
+ );
+
+ $this->assertEquals(
+ [ 'doSomethingElse' ],
+ $instance->get( 'Schema.if.and' )
+ );
+ }
+
+ public function testJsonSerialize() {
+
+ $def = [
+ 'type' => 'foo_bar',
+ 'description' => 'bar foo bar',
+ 'Schema' => [
+ 'if' => [
+ 'doSomething',
+ 'and' => [
+ 'doSomethingElse'
+ ]
+ ],
+ 'then' => [
+ ]
+ ]
+ ];
+
+ $instance = new SchemaDefinition(
+ 'foo',
+ $def
+ );
+
+ $this->assertEquals(
+ json_encode( $def ),
+ $instance->jsonSerialize()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaFactoryTest.php
new file mode 100644
index 00000000..b0dc7562
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaFactoryTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace SMW\Tests\Schema;
+
+use SMW\Schema\SchemaFactory;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Schema\SchemaFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SchemaFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $instance = new SchemaFactory();
+
+ $this->assertInstanceof(
+ SchemaFactory::class,
+ $instance
+ );
+ }
+
+ public function testCanConstructSchemaValidator() {
+
+ $instance = new SchemaFactory();
+
+ $this->assertInstanceof(
+ '\SMW\Schema\SchemaValidator',
+ $instance->newSchemaValidator()
+ );
+ }
+
+ public function testIsRegisteredType() {
+
+ $instance = new SchemaFactory(
+ [
+ 'foo' => []
+ ]
+ );
+
+ $this->assertTrue(
+ $instance->isRegisteredType( 'foo' )
+ );
+ }
+
+ public function testGetRegisteredTypes() {
+
+ $instance = new SchemaFactory(
+ [
+ 'foo' => [],
+ 'bar' => []
+ ]
+ );
+
+ $this->assertEquals(
+ [ 'foo', 'bar' ],
+ $instance->getRegisteredTypes()
+ );
+ }
+
+ public function testGetRegisteredTypesByGroup() {
+
+ $instance = new SchemaFactory(
+ [
+ 'foo' => [ 'group' => 'f_group' ],
+ 'bar' => [ 'group' => 'b_group' ]
+ ]
+ );
+
+ $this->assertEquals(
+ [ 'foo' ],
+ $instance->getRegisteredTypesByGroup( 'f_group' )
+ );
+ }
+
+ public function testNewSchemaDefinition() {
+
+ $instance = new SchemaFactory(
+ [
+ 'foo' => [ 'group' => 'f_group' ]
+ ]
+ );
+
+ $this->assertInstanceof(
+ '\SMW\Schema\SchemaDefinition',
+ $instance->newSchema( 'foo_bar', [ 'type' => 'foo' ] )
+ );
+ }
+
+ public function testNewSchemaDefinitionOnUnknownTypeThrowsException() {
+
+ $instance = new SchemaFactory();
+
+ $this->setExpectedException( '\SMW\Schema\Exception\SchemaTypeNotFoundException' );
+ $instance->newSchema( 'foo_bar', [ 'type' => 'foo' ] );
+ }
+
+ public function testNewSchemaDefinitionOnNoTypeThrowsException() {
+
+ $instance = new SchemaFactory(
+ [
+ 'foo' => [ 'group' => 'f_group' ]
+ ]
+ );
+
+ $this->setExpectedException( '\SMW\Schema\Exception\SchemaTypeNotFoundException' );
+ $instance->newSchema( 'foo_bar', [] );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaValidatorTest.php
new file mode 100644
index 00000000..0f81f50d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Schema/SchemaValidatorTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Schema;
+
+use SMW\DataItemFactory;
+use SMW\Schema\SchemaValidator;
+use SMW\Schema\SchemaDefinition;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMW\Schema\SchemaValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SchemaValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $jsonSchemaValidator = $this->getMockBuilder( '\SMW\Utils\JsonSchemaValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ SchemaValidator::class,
+ new SchemaValidator( $jsonSchemaValidator )
+ );
+ }
+
+ public function testValidate_IsValid() {
+
+ $jsonSchemaValidator = $this->getMockBuilder( '\SMW\Utils\JsonSchemaValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jsonSchemaValidator->expects( $this->once() )
+ ->method( 'validate' )
+ ->will( $this->returnValue( false ) );
+
+ $jsonSchemaValidator->expects( $this->once() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new SchemaValidator( $jsonSchemaValidator );
+
+ $this->assertEmpty(
+ $instance->validate( new SchemaDefinition( 'foo', [], '...' ) )
+ );
+ }
+
+ public function testValidate_Error() {
+
+ $jsonSchemaValidator = $this->getMockBuilder( '\SMW\Utils\JsonSchemaValidator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jsonSchemaValidator->expects( $this->once() )
+ ->method( 'validate' )
+ ->will( $this->returnValue( false ) );
+
+ $jsonSchemaValidator->expects( $this->once() )
+ ->method( 'isValid' )
+ ->will( $this->returnValue( false ) );
+
+ $jsonSchemaValidator->expects( $this->once() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [ '...' ] ) );
+
+ $instance = new SchemaValidator( $jsonSchemaValidator );
+
+ $this->assertNotEmpty(
+ $instance->validate( new SchemaDefinition( 'foo', [], '...' ) )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SerializerFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SerializerFactoryTest.php
new file mode 100644
index 00000000..149dbec3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SerializerFactoryTest.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\SerializerFactory;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\SerializerFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SerializerFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\SerializerFactory',
+ new SerializerFactory()
+ );
+ }
+
+ public function testCanConstructSemanticDataSerializer() {
+
+ $instance = new SerializerFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Serializers\SemanticDataSerializer',
+ $instance->newSemanticDataSerializer()
+ );
+ }
+
+ public function testCanConstructSemanticDataDeserializer() {
+
+ $instance = new SerializerFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\SemanticDataDeserializer',
+ $instance->newSemanticDataDeserializer()
+ );
+ }
+
+ public function testCanConstructQueryResultSerializer() {
+
+ $instance = new SerializerFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Serializers\QueryResultSerializer',
+ $instance->newQueryResultSerializer()
+ );
+ }
+
+ public function testCanConstructExpDataSerializer() {
+
+ $instance = new SerializerFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Serializers\ExpDataSerializer',
+ $instance->newExpDataSerializer()
+ );
+ }
+
+ public function testCanConstructExpDataDeserializer() {
+
+ $instance = new SerializerFactory();
+
+ $this->assertInstanceOf(
+ '\SMW\Deserializers\ExpDataDeserializer',
+ $instance->newExpDataDeserializer()
+ );
+ }
+
+ /**
+ * @dataProvider objectToSerializerProvider
+ */
+ public function testGetSerializerFor( $object ) {
+
+ $instance = new SerializerFactory();
+
+ $this->assertInstanceOf(
+ '\Serializers\Serializer',
+ $instance->getSerializerFor( $object )
+ );
+ }
+
+ /**
+ * @dataProvider serializationToDeserializerProvider
+ */
+ public function testGetDeserializerFor( $serialization ) {
+
+ $instance = new SerializerFactory();
+
+ $this->assertInstanceOf(
+ '\Deserializers\Deserializer',
+ $instance->getDeserializerFor( $serialization )
+ );
+ }
+
+ public function testGetSerializerForUnregisteredSerializerThrowsException() {
+
+ $instance = new SerializerFactory();
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+ $instance->getSerializerFor( 'Foo' );
+ }
+
+ public function testGetDeserializerForUnregisteredSerializerThrowsException() {
+
+ $instance = new SerializerFactory();
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+ $instance->getDeserializerFor( [ 'Foo' ] );
+ }
+
+ public function objectToSerializerProvider() {
+
+ #0
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ $semanticData
+ ];
+
+ #1
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ $queryResult
+ ];
+
+ #2
+ $queryResult = $this->getMockBuilder( '\SMWExpData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ $queryResult
+ ];
+
+ return $provider;
+ }
+
+ public function serializationToDeserializerProvider() {
+
+ $provider = [];
+
+ #0
+ $provider[] = [
+ [ 'serializer' => 'SMW\Serializers\SemanticDataSerializer', 'subject' => 'Foo#0##' ]
+ ];
+
+ #1
+ $provider[] = [
+ [ 'serializer' => 'SMW\Serializers\ExpDataSerializer' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/ExpDataSerializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/ExpDataSerializerTest.php
new file mode 100644
index 00000000..9e38a8d7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/ExpDataSerializerTest.php
@@ -0,0 +1,174 @@
+<?php
+
+namespace SMW\Tests\Serializers;
+
+use SMW\Exporter\Element\ExpLiteral;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Serializers\ExpDataSerializer;
+use SMWDIBlob as DIBlob;
+use SMWExpData as ExpData;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Serializers\ExpDataSerializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpDataSerializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstructor() {
+
+ $this->assertInstanceOf(
+ '\SMW\Serializers\ExpDataSerializer',
+ new ExpDataSerializer()
+ );
+ }
+
+ public function testInvalidSerializerObjectThrowsException() {
+
+ $instance = new ExpDataSerializer();
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+ $instance->serialize( 'Foo' );
+ }
+
+ /**
+ * @dataProvider expDataProvider
+ */
+ public function testSerialize( $data, $expected ) {
+
+ $instance = new ExpDataSerializer();
+
+ $this->assertEquals(
+ $expected,
+ $instance->serialize( $data )
+ );
+ }
+
+ public function expDataProvider() {
+
+ #0
+ $expData = new ExpData( new ExpNsResource( 'Foo', 'Bar', 'Mo', null ) );
+
+ $provider[] = [
+ $expData,
+ [
+ 'subject' => [
+ 'type' => 1,
+ 'uri' => 'Foo|Bar|Mo',
+ 'dataitem' => null
+ ],
+ 'data' => [],
+ 'serializer' => 'SMW\Serializers\ExpDataSerializer',
+ 'version' => 0.1
+ ]
+ ];
+
+ #1
+ $expData = new ExpData( new ExpNsResource( 'Foo', 'Bar', 'Mo', null ) );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $provider[] = [
+ $expData,
+ [
+ 'subject' => [
+ 'type' => 1,
+ 'uri' => 'Foo|Bar|Mo',
+ 'dataitem' => null
+ ],
+ 'data' => [
+ 'LaLi' => [
+ 'property' => [
+ 'type' => 1,
+ 'uri' => 'Li|La|Lu',
+ 'dataitem' => null
+ ],
+ 'children' => [
+ [
+ 'type' => 2,
+ 'lexical' => 'Foo',
+ 'datatype' => 'Bar',
+ 'lang' => '',
+ 'dataitem' => null
+ ]
+ ]
+ ]
+ ],
+ 'serializer' => 'SMW\Serializers\ExpDataSerializer',
+ 'version' => 0.1
+ ]
+ ];
+
+ #2 Nested
+ $expData = new ExpData( new ExpNsResource( 'Foo', 'Bar', 'Mo', null ) );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', new DIBlob( 'SomeText' ) ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpData( new ExpNsResource( 'Foo', 'Bar', 'Mo', new DIBlob( 'SomeOtherText' ) ) )
+ );
+
+ $provider[] = [
+ $expData,
+ [
+ 'subject' => [
+ 'type' => 1,
+ 'uri' => 'Foo|Bar|Mo',
+ 'dataitem' => null
+ ],
+ 'data' => [
+ 'LaLi' => [
+ 'property' => [
+ 'type' => 1,
+ 'uri' => 'Li|La|Lu',
+ 'dataitem' => [ // DIBlob
+ 'type' => 2,
+ 'item' => 'SomeText'
+ ]
+ ],
+ 'children' => [
+ [ // ExpLiteral
+ 'type' => 2,
+ 'lexical' => 'Foo',
+ 'datatype' => 'Bar',
+ 'lang' => '',
+ 'dataitem' => null
+ ],
+ [ // ExpData
+ 'subject' => [
+ 'type' => 1,
+ 'uri' => 'Foo|Bar|Mo',
+ 'dataitem' => [
+ 'type' => 2,
+ 'item' => 'SomeOtherText'
+ ]
+ ],
+ 'data' => []
+ ]
+ ]
+ ]
+ ],
+ 'serializer' => 'SMW\Serializers\ExpDataSerializer',
+ 'version' => 0.1
+ ]
+ ];
+
+ return $provider;
+ }
+
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/QueryResultSerializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/QueryResultSerializerTest.php
new file mode 100644
index 00000000..c468b25e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/QueryResultSerializerTest.php
@@ -0,0 +1,286 @@
+<?php
+
+namespace SMW\Tests\Serializers;
+
+use SMW\DataItemFactory;
+use SMW\Serializers\QueryResultSerializer;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\CoreMockObjectRepository;
+use SMW\Tests\Utils\Mock\MediaWikiMockObjectRepository;
+use SMW\Tests\Utils\Mock\MockObjectBuilder;
+use SMWDataItem as DataItem;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Serializers\QueryResultSerializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class QueryResultSerializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $testEnvironment;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstructor() {
+
+ $this->assertInstanceOf(
+ '\SMW\Serializers\QueryResultSerializer',
+ new QueryResultSerializer()
+ );
+ }
+
+ public function testSerializeOutOfBoundsException() {
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+
+ $instance = new QueryResultSerializer();
+ $instance->serialize( 'Foo' );
+ }
+
+ /**
+ * @dataProvider numberDataProvider
+ */
+ public function testQueryResultSerializerOnMock( $setup, $expected ) {
+
+ $instance = new QueryResultSerializer();
+ $results = $instance->serialize( $setup['queryResult'] );
+
+ $this->assertInternalType(
+ 'array',
+ $results
+ );
+
+ $this->assertEquals(
+ $expected['printrequests'],
+ $results['printrequests']
+ );
+ }
+
+ public function testQueryResultSerializerForRecordType() {
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIProperty( 'Foobar' ) ] ) );
+
+ $semanticData->expects( $this->atLeastOnce() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $this->dataItemFactory->newDIWikiPage( 'Bar', NS_MAIN ) ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getSemanticData' )
+ ->will( $this->returnValue( $semanticData ) );
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getFieldListBy' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'BarList1;BarList2' ) ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $property = \SMW\DIProperty::newFromUserLabel( 'Foo' );
+ $property->setPropertyTypeId( '_rec' );
+
+ $printRequestFactory = new \SMW\Query\PrintRequestFactory();
+
+ $serialization = QueryResultSerializer::getSerialization(
+ \SMW\DIWikiPage::newFromText( 'ABC' ),
+ $printRequestFactory->newFromProperty( $property )
+ );
+
+ $expected = [
+ 'BarList1' => [
+ 'label' => 'BarList1',
+ 'typeid' => '_wpg',
+ 'item' => [],
+ 'key' => 'BarList1'
+ ],
+ 'BarList2' => [
+ 'label' => 'BarList2',
+ 'typeid' => '_wpg',
+ 'item' => [],
+ 'key' => 'BarList2'
+ ]
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $serialization
+ );
+ }
+
+ public function testSerializeFormatForTimeValue() {
+
+ $property = \SMW\DIProperty::newFromUserLabel( 'Foo' );
+ $property->setPropertyTypeId( '_dat' );
+
+ $printRequestFactory = new \SMW\Query\PrintRequestFactory();
+
+ $serialization = QueryResultSerializer::getSerialization(
+ \SMWDITime::doUnserialize( '2/1393/1/1' ),
+ $printRequestFactory->newFromProperty( $property )
+ );
+
+ $expected = [
+ 'timestamp' => '-18208281600',
+ 'raw' => '2/1393/1/1'
+ ];
+
+ $this->assertEquals(
+ $expected,
+ $serialization
+ );
+ }
+
+ public function testQueryResultSerializerOnMockOnDIWikiPageNonTitle() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataItem = $this->newMockBuilder()->newObject( 'DataItem', [
+ 'getDIType' => DataItem::TYPE_WIKIPAGE,
+ 'getTitle' => null
+ ] );
+
+ $queryResult = $this->newMockBuilder()->newObject( 'QueryResult', [
+ 'getPrintRequests' => [],
+ 'getResults' => [ $dataItem ],
+ 'getQuery' => $query
+ ] );
+
+ $instance = new QueryResultSerializer();
+ $results = $instance->serialize( $queryResult );
+
+ $this->assertInternalType( 'array', $results );
+ $this->assertEmpty( $results['printrequests'] );
+ $this->assertEmpty( $results['results'] );
+ }
+
+ /**
+ * @return array
+ */
+ public function numberDataProvider() {
+
+ $provider = [];
+
+ $setup = [
+ [ 'printRequest' => 'Foo-1', 'typeId' => '_num', 'number' => 10, 'dataValue' => 'Quuey' ],
+ [ 'printRequest' => 'Foo-2', 'typeId' => '_num', 'number' => 20, 'dataValue' => 'Vey' ],
+ ];
+
+ $provider[] = [
+ [
+ 'queryResult' => $this->buildMockQueryResult( $setup )
+ ],
+ [
+ 'printrequests' => [
+ [ 'label' => 'Foo-1', 'typeid' => '_num', 'mode' => 2, 'format' => false, 'key' => '', 'redi' => '' ],
+ [ 'label' => 'Foo-2', 'typeid' => '_num', 'mode' => 2, 'format' => false, 'key' => '', 'redi' => '' ]
+ ],
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return QueryResult
+ */
+ private function buildMockQueryResult( $setup ) {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequests = [];
+ $resultArray = [];
+ $getResults = [];
+
+ foreach ( $setup as $value ) {
+
+ $printRequest = $this->newMockBuilder()->newObject( 'PrintRequest', [
+ 'getText' => $value['printRequest'],
+ 'getLabel' => $value['printRequest'],
+ 'getTypeID' => $value['typeId'],
+ 'getOutputFormat' => false
+ ] );
+
+ $printRequests[] = $printRequest;
+ $getResults[] = \SMW\DIWikiPage::newFromTitle( new \Title( NS_MAIN, $value['printRequest'] ) );
+
+ $dataItem = $this->newMockBuilder()->newObject( 'DataItem', [
+ 'getDIType' => DataItem::TYPE_NUMBER,
+ 'getNumber' => $value['number']
+ ] );
+
+ $dataValue = $this->newMockBuilder()->newObject( 'DataValue', [
+ 'DataValueType' => 'SMWNumberValue',
+ 'getTypeID' => '_num',
+ 'getShortWikiText' => $value['dataValue'],
+ 'getDataItem' => $dataItem
+ ] );
+
+ $resultArray[] = $this->newMockBuilder()->newObject( 'ResultArray', [
+ 'getText' => $value['printRequest'],
+ 'getPrintRequest' => $printRequest,
+ 'getNextDataValue' => $dataValue,
+ 'getNextDataItem' => $dataItem,
+ 'getContent' => $dataItem
+ ] );
+
+ }
+
+ $queryResult = $this->newMockBuilder()->newObject( 'QueryResult', [
+ 'getPrintRequests' => $printRequests,
+ 'getNext' => $resultArray,
+ 'getResults' => $getResults,
+ 'getQuery' => $query,
+ 'getStore' => $this->newMockBuilder()->newObject( 'Store' ),
+ 'getLink' => new \SMWInfolink( true, 'Lala', 'Lula' ),
+ 'hasFurtherResults' => true
+ ] );
+
+ return $queryResult;
+ }
+
+ private function newMockBuilder() {
+
+ $builder = new MockObjectBuilder();
+ $builder->registerRepository( new CoreMockObjectRepository() );
+ $builder->registerRepository( new MediaWikiMockObjectRepository() );
+
+ return $builder;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/SemanticDataSerializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/SemanticDataSerializerTest.php
new file mode 100644
index 00000000..2a24cab0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Serializers/SemanticDataSerializerTest.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace SMW\Tests\Serializers;
+
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\Serializers\SemanticDataSerializer;
+use SMW\Subobject;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Serializers\SemanticDataSerializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SemanticDataSerializerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $dataValueFactory;
+ private $semanticDataFactory;
+
+ public function testCanConstructor() {
+
+ $this->assertInstanceOf(
+ '\SMW\Serializers\SemanticDataSerializer',
+ new SemanticDataSerializer()
+ );
+ }
+
+ public function testInvalidSerializerObjectThrowsException() {
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+
+ $instance = new SemanticDataSerializer();
+ $instance->serialize( 'Foo' );
+ }
+
+ /**
+ * @dataProvider semanticDataProvider
+ */
+ public function testSerializerDeserializerRountrip( $data ) {
+
+ $instance = new SemanticDataSerializer();
+
+ $this->assertInternalType(
+ 'array',
+ $instance->serialize( $data )
+ );
+ }
+
+ public function semanticDataProvider() {
+
+ // Is a dataprovider therefore can't use the setUp
+ $this->semanticDataFactory = UtilityFactory::getInstance()->newSemanticDataFactory();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+
+ $title = Title::newFromText( 'Foo' );
+
+ #0 Empty container
+ $foo = $this->semanticDataFactory->setSubject( DIWikiPage::newFromTitle( $title ) )->newEmptySemanticData();
+ $provider[] = [ $foo ];
+
+ #1 Single entry
+ $foo = $this->semanticDataFactory->setSubject( DIWikiPage::newFromTitle( $title ) )->newEmptySemanticData();
+ $foo->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+ $provider[] = [ $foo ];
+
+ // #2 Single + single subobject entry
+ $foo = $this->semanticDataFactory->setSubject( DIWikiPage::newFromTitle( $title ) )->newEmptySemanticData();
+ $foo->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has subobjects', 'Bam' ) );
+
+ $foo->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $provider[] = [ $foo ];
+
+ #3 Multiple entries
+ $foo = $this->semanticDataFactory->setSubject( DIWikiPage::newFromTitle( $title ) )->newEmptySemanticData();
+ $foo->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has fooQuex', 'Bar' ) );
+ $foo->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has queez', 'Xeey' ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has subobjects', 'Bam' ) );
+ $subobject->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has fooQuex', 'Fuz' ) );
+
+ $subobject->setSemanticData( 'Bar' );
+ $subobject->addDataValue( $this->dataValueFactory->newDataValueByText( 'Has fooQuex', 'Fuz' ) );
+
+ $foo->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $provider[] = [ $foo ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServiceFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServiceFactoryTest.php
new file mode 100644
index 00000000..58f3a8ad
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServiceFactoryTest.php
@@ -0,0 +1,189 @@
+<?php
+
+namespace SMW\Tests\Services;
+
+use SMW\Services\DataValueServiceFactory;
+
+/**
+ * @covers \SMW\Services\DataValueServiceFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DataValueServiceFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $containerBuilder;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->containerBuilder = $this->getMockBuilder( '\Onoi\CallbackContainer\ContainerBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ DataValueServiceFactory::class,
+ new DataValueServiceFactory( $this->containerBuilder )
+ );
+ }
+
+ public function testGetServiceFile() {
+
+ $this->assertInternalType(
+ 'string',
+ DataValueServiceFactory::SERVICE_FILE
+ );
+ }
+
+ public function testNewDataValueByType() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->containerBuilder->expects( $this->once() )
+ ->method( 'isRegistered' )
+ ->with( $this->stringContains( DataValueServiceFactory::TYPE_INSTANCE . 'foo' ) )
+ ->will( $this->returnValue( true ) );
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $instance->newDataValueByType( 'foo', 'bar' );
+ }
+
+ public function testGetDataValueFactory() {
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\DataValueFactory',
+ $instance->getDataValueFactory()
+ );
+ }
+
+ public function testGetValueParser() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->containerBuilder->expects( $this->once() )
+ ->method( 'singleton' )
+ ->with( $this->stringContains( DataValueServiceFactory::TYPE_PARSER ) );
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $instance->getValueParser( $dataValue );
+ }
+
+ public function testGetValueFormatterOnRegisteredFormatters() {
+
+ $dataValueFormatter = $this->getMockBuilder( '\SMW\DataValues\ValueFormatters\DataValueFormatter' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->containerBuilder->expects( $this->once() )
+ ->method( 'isRegistered' )
+ ->will( $this->returnValue( true ) );
+
+ $this->containerBuilder->expects( $this->once() )
+ ->method( 'singleton' )
+ ->with( $this->stringContains( DataValueServiceFactory::TYPE_FORMATTER ) )
+ ->will( $this->returnValue( $dataValueFormatter ) );
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $instance->getValueFormatter( $dataValue );
+ }
+
+ public function testGetValueFormatterOnNonRegisteredFormatters() {
+
+ $dataValueFormatter = $this->getMockBuilder( '\SMW\DataValues\ValueFormatters\DataValueFormatter' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->containerBuilder->expects( $this->once() )
+ ->method( 'isRegistered' )
+ ->will( $this->returnValue( false ) );
+
+ $this->containerBuilder->expects( $this->atLeastOnce() )
+ ->method( 'singleton' )
+ ->with( $this->stringContains( DataValueServiceFactory::TYPE_FORMATTER ) )
+ ->will( $this->returnValue( $dataValueFormatter ) );
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $instance->getValueFormatter( $dataValue );
+ }
+
+ public function testImportExtraneousFunctions() {
+
+ $this->containerBuilder->expects( $this->atLeastOnce() )
+ ->method( 'registerCallback' )
+ ->with( $this->stringContains( DataValueServiceFactory::TYPE_EXT_FUNCTION . 'Foo' ) );
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $instance->importExtraneousFunctions( [
+ 'Foo' => function() { return 'Foo'; }
+ ] );
+ }
+
+ public function testNewExtraneousFunctionByName() {
+
+ $this->containerBuilder->expects( $this->atLeastOnce() )
+ ->method( 'create' )
+ ->with( $this->stringContains( DataValueServiceFactory::TYPE_EXT_FUNCTION . 'Foo' ) );
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $instance->newExtraneousFunctionByName( 'Foo' );
+ }
+
+ public function testGetPropertyRestrictionExaminer() {
+
+ $propertyRestrictionExaminer = $this->getMockBuilder( '\SMW\PropertyRestrictionExaminer' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->containerBuilder->expects( $this->atLeastOnce() )
+ ->method( 'singleton' )
+ ->with( $this->stringContains( 'PropertyRestrictionExaminer' ) )
+ ->will( $this->returnValue( $propertyRestrictionExaminer ) );
+
+ $instance = new DataValueServiceFactory(
+ $this->containerBuilder
+ );
+
+ $instance->getPropertyRestrictionExaminer();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServicesContainerBuildTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServicesContainerBuildTest.php
new file mode 100644
index 00000000..383d4522
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/DataValueServicesContainerBuildTest.php
@@ -0,0 +1,171 @@
+<?php
+
+namespace SMW\Tests\Services;
+
+use Onoi\CallbackContainer\CallbackContainerFactory;
+use SMW\DataValues\AllowsListValue;
+use SMW\DataValues\AllowsPatternValue;
+use SMW\DataValues\MonolingualTextValue;
+use SMW\DataValues\ReferenceValue;
+use SMW\DataValues\StringValue;
+use SMW\DataValues\ValueFormatters\CodeStringValueFormatter;
+use SMW\DataValues\ValueFormatters\MonolingualTextValueFormatter;
+use SMW\DataValues\ValueFormatters\NumberValueFormatter;
+use SMW\DataValues\ValueFormatters\PropertyValueFormatter;
+use SMW\DataValues\ValueFormatters\ReferenceValueFormatter;
+use SMW\DataValues\ValueFormatters\StringValueFormatter;
+use SMW\DataValues\ValueFormatters\TimeValueFormatter;
+use SMW\DataValues\ValueParsers\AllowsListValueParser;
+use SMW\DataValues\ValueParsers\AllowsPatternValueParser;
+use SMW\DataValues\ValueParsers\MonolingualTextValueParser;
+use SMW\DataValues\ValueParsers\PropertyValueParser;
+use SMW\DataValues\ValueValidators\CompoundConstraintValueValidator;
+use SMW\Services\DataValueServiceFactory;
+use SMW\Settings;
+use SMWNumberValue as NumberValue;
+use SMWPropertyValue as PropertyValue;
+use SMWTimeValue as TimeValue;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class DataValueServicesContainerBuildTest extends \PHPUnit_Framework_TestCase {
+
+ private $callbackContainerFactory;
+ private $servicesFileDir;
+ private $mediaWikiNsContentReader;
+ private $propertySpecificationLookup;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->mediaWikiNsContentReader = $this->getMockBuilder( '\SMW\MediaWiki\MediaWikiNsContentReader' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->callbackContainerFactory = new CallbackContainerFactory();
+ $this->servicesFileDir = $GLOBALS['smwgServicesFileDir'];
+ }
+
+ /**
+ * @dataProvider servicesProvider
+ */
+ public function testCanConstruct( $service, $parameters, $expected ) {
+
+ array_unshift( $parameters, $service );
+
+ $containerBuilder = $this->callbackContainerFactory->newCallbackContainerBuilder();
+
+ $containerBuilder->registerObject( 'Settings', new Settings( [
+ 'smwgPropertyInvalidCharacterList' => [ 'Foo' ] ]
+ ) );
+
+ $containerBuilder->registerObject( 'MediaWikiNsContentReader', $this->mediaWikiNsContentReader );
+ $containerBuilder->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ $containerBuilder->registerObject( 'Store', $this->store );
+
+ $containerBuilder->registerFromFile( $this->servicesFileDir . '/' . 'DataValueServices.php' );
+
+ $this->assertInstanceOf(
+ $expected,
+ call_user_func_array( [ $containerBuilder, 'create' ], $parameters )
+ );
+ }
+
+ public function servicesProvider() {
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_PARSER . PropertyValue::TYPE_ID,
+ [],
+ PropertyValueParser::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . PropertyValue::TYPE_ID,
+ [],
+ PropertyValueFormatter::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_PARSER . AllowsPatternValue::TYPE_ID,
+ [],
+ AllowsPatternValueParser::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_PARSER . AllowsListValue::TYPE_ID,
+ [],
+ AllowsListValueParser::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_VALIDATOR . 'CompoundConstraintValueValidator',
+ [],
+ CompoundConstraintValueValidator::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . StringValue::TYPE_ID,
+ [],
+ StringValueFormatter::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . StringValue::TYPE_COD_ID,
+ [],
+ CodeStringValueFormatter::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . ReferenceValue::TYPE_ID,
+ [],
+ ReferenceValueFormatter::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . ReferenceValue::TYPE_ID,
+ [],
+ ReferenceValueFormatter::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_PARSER . MonolingualTextValue::TYPE_ID,
+ [],
+ MonolingualTextValueParser::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . MonolingualTextValue::TYPE_ID,
+ [],
+ MonolingualTextValueFormatter::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . NumberValue::TYPE_ID,
+ [],
+ NumberValueFormatter::class
+ ];
+
+ $provider[] = [
+ DataValueServiceFactory::TYPE_FORMATTER . TimeValue::TYPE_ID,
+ [],
+ TimeValueFormatter::class
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/Exception/ServiceNotFoundExceptionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/Exception/ServiceNotFoundExceptionTest.php
new file mode 100644
index 00000000..4949fb1e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/Exception/ServiceNotFoundExceptionTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Services\Exception;
+
+use SMW\Services\Exception\ServiceNotFoundException;
+
+/**
+ * @covers \SMW\Services\Exception\ServiceNotFoundException
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ServiceNotFoundExceptionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new ServiceNotFoundException( 'foo' );
+
+ $this->assertInstanceof(
+ ServiceNotFoundException::class,
+ $instance
+ );
+
+ $this->assertInstanceof(
+ '\InvalidArgumentException',
+ $instance
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServiceFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServiceFactoryTest.php
new file mode 100644
index 00000000..4551deed
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServiceFactoryTest.php
@@ -0,0 +1,133 @@
+<?php
+
+namespace SMW\Tests\Services;
+
+use Onoi\CallbackContainer\CallbackContainerFactory;
+use SMW\Services\ImporterServiceFactory;
+use SMW\Settings;
+
+/**
+ * @covers \SMW\Services\ImporterServiceFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ImporterServiceFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ private $containerBuilder;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $callbackContainerFactory = new CallbackContainerFactory();
+
+ $this->containerBuilder = $callbackContainerFactory->newCallbackContainerBuilder();
+
+ $pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->containerBuilder->registerObject( 'PageCreator', $pageCreator );
+
+ $importStringSource = $this->getMockBuilder( '\ImportStringSource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->containerBuilder->registerObject( 'ImportStringSource', $importStringSource );
+
+ $wikiImporter = $this->getMockBuilder( '\WikiImporter' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->containerBuilder->registerObject( 'WikiImporter', $wikiImporter );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->containerBuilder->registerObject( 'ConnectionManager', $connectionManager );
+
+ $this->containerBuilder->registerObject( 'Settings', new Settings( [
+ 'smwgImportReqVersion' => 1,
+ 'smwgImportFileDirs' => 'foo'
+ ] ) );
+
+ $this->containerBuilder->registerFromFile( $GLOBALS['smwgServicesFileDir'] . '/' . 'ImporterServices.php' );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ImporterServiceFactory::class,
+ new ImporterServiceFactory( $this->containerBuilder )
+ );
+ }
+
+ public function testCanConstructImportStringSource() {
+
+ $instance = new ImporterServiceFactory(
+ $this->containerBuilder
+ );
+
+ $this->assertInstanceOf(
+ '\ImportStringSource',
+ $instance->newImportStringSource( 'Foo' )
+ );
+ }
+
+ public function testCanConstructWikiImporter() {
+
+ $importSource = $this->getMockBuilder( '\ImportSource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ImporterServiceFactory(
+ $this->containerBuilder
+ );
+
+ $this->assertInstanceOf(
+ '\WikiImporter',
+ $instance->newWikiImporter( $importSource )
+ );
+ }
+
+ public function testCanConstructImporter() {
+
+ $contentIterator = $this->getMockBuilder( '\SMW\Importer\ContentIterator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $instance = new ImporterServiceFactory(
+ $this->containerBuilder
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\Importer',
+ $instance->newImporter( $contentIterator )
+ );
+ }
+
+ public function testCanConstructJsonContentIterator() {
+
+ $instance = new ImporterServiceFactory(
+ $this->containerBuilder
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\Importer\JsonContentIterator',
+ $instance->newJsonContentIterator( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServicesContainerBuildTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServicesContainerBuildTest.php
new file mode 100644
index 00000000..52ed7ab7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ImporterServicesContainerBuildTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\Services;
+
+use Onoi\CallbackContainer\CallbackContainerFactory;
+use SMW\Settings;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ImporterServicesContainerBuildTest extends \PHPUnit_Framework_TestCase {
+
+ private $callbackContainerFactory;
+ private $connectionManager;
+ private $servicesFileDir;
+ private $pageCreator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->pageCreator = $this->getMockBuilder( '\SMW\MediaWiki\PageCreator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connectionManager = $this->getMockBuilder( '\SMW\Connection\ConnectionManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->connectionManager->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->callbackContainerFactory = new CallbackContainerFactory();
+ $this->servicesFileDir = $GLOBALS['smwgServicesFileDir'];
+ }
+
+ /**
+ * @dataProvider servicesProvider
+ */
+ public function testCanConstruct( $service, $parameters, $expected ) {
+
+ array_unshift( $parameters, $service );
+
+ $containerBuilder = $this->callbackContainerFactory->newCallbackContainerBuilder();
+
+ $containerBuilder->registerObject( 'PageCreator', $this->pageCreator );
+ $containerBuilder->registerObject( 'ConnectionManager', $this->connectionManager );
+
+ $containerBuilder->registerObject( 'Settings', new Settings( [
+ 'smwgImportReqVersion' => 1,
+ 'smwgImportFileDirs' => [ 'foo' ]
+ ] ) );
+
+ $containerBuilder->registerFromFile( $this->servicesFileDir . '/' . 'ImporterServices.php' );
+
+ $this->assertInstanceOf(
+ $expected,
+ call_user_func_array( [ $containerBuilder, 'create' ], $parameters )
+ );
+ }
+
+ public function servicesProvider() {
+
+ $contentIterator = $this->getMockBuilder( '\SMW\Importer\ContentIterator' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ 'Importer',
+ [ $contentIterator ],
+ '\SMW\Importer\Importer'
+ ];
+
+ $provider[] = [
+ 'JsonContentIterator',
+ [ 'SomeDirectory' ],
+ '\SMW\Importer\JsonContentIterator'
+ ];
+
+ $provider[] = [
+ 'ImporterServiceFactory',
+ [],
+ '\SMW\Services\ImporterServiceFactory'
+ ];
+
+ $provider[] = [
+ 'XmlContentCreator',
+ [],
+ '\SMW\Importer\ContentCreators\XmlContentCreator'
+ ];
+
+ $provider[] = [
+ 'TextContentCreator',
+ [],
+ '\SMW\Importer\ContentCreators\TextContentCreator'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/MediaWikiServicesContainerBuildTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/MediaWikiServicesContainerBuildTest.php
new file mode 100644
index 00000000..99b448fb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/MediaWikiServicesContainerBuildTest.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace SMW\Tests\Services;
+
+use Onoi\CallbackContainer\CallbackContainerFactory;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class MediaWikiServicesContainerBuildTest extends \PHPUnit_Framework_TestCase {
+
+ private $callbackContainerFactory;
+ private $servicesFileDir;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->callbackContainerFactory = new CallbackContainerFactory();
+ $this->servicesFileDir = $GLOBALS['smwgServicesFileDir'];
+ }
+
+ /**
+ * @dataProvider servicesProvider
+ */
+ public function testCanConstruct( $service, $parameters, $expected ) {
+
+ array_unshift( $parameters, $service );
+
+ $containerBuilder = $this->callbackContainerFactory->newCallbackContainerBuilder();
+ $containerBuilder->registerFromFile( $this->servicesFileDir . '/' . 'MediaWikiServices.php' );
+
+ $this->assertInstanceOf(
+ $expected,
+ call_user_func_array( [ $containerBuilder, 'create' ], $parameters )
+ );
+ }
+
+ public function servicesProvider() {
+
+ $title = $this->getMockBuilder( '\Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = [
+ 'WikiPage',
+ [ $title ],
+ '\WikiPage'
+ ];
+
+ $provider[] = [
+ 'DBLoadBalancer',
+ [],
+ '\LoadBalancer'
+ ];
+
+/*
+ $database = $this->getMockBuilder( '\DatabaeBase' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $provider[] = array(
+ 'DefaultSearchEngineTypeForDB',
+ array( $database ),
+ '\SearchEngine'
+ );
+*/
+
+ $provider[] = [
+ 'MediaWikiLogger',
+ [],
+ '\Psr\Log\LoggerInterface'
+ ];
+
+ $provider[] = [
+ 'JobQueueGroup',
+ [],
+ '\JobQueueGroup'
+ ];
+
+ return $provider;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ServicesContainerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ServicesContainerTest.php
new file mode 100644
index 00000000..7f4082b9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/ServicesContainerTest.php
@@ -0,0 +1,149 @@
+<?php
+
+namespace SMW\Tests\Services;
+
+use SMW\Services\ServicesContainer;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Services\ServicesContainer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ServicesContainerTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ ServicesContainer::class,
+ new ServicesContainer()
+ );
+ }
+
+ public function testGet() {
+
+ $mock = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'runService' ] )
+ ->getMock();
+
+ $mock->expects( $this->once() )
+ ->method( 'runService' );
+
+ $instance = new ServicesContainer(
+ [
+ 'test' => [ $this, 'fakeService' ]
+ ]
+ );
+
+ $instance->get( 'test', $mock );
+ }
+
+ public function testGetTypedService() {
+
+ $instance = new ServicesContainer(
+ [
+ 'test' => [
+ '_service' => [ $this, 'stdClassService' ],
+ '_type' => '\stdClass'
+ ]
+ ]
+ );
+
+ $this->assertInstanceOf(
+ '\stdClass',
+ $instance->get( 'test' )
+ );
+ }
+
+ public function testGet_MultipleArgs() {
+
+ $fake = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'runService' ] )
+ ->getMock();
+
+ $fake->expects( $this->once() )
+ ->method( 'runService' )
+ ->with( $this->stringContains( 'FOO' ) );
+
+ $instance = new ServicesContainer(
+ [
+ 'test' => [ $this, 'fakeService' ]
+ ]
+ );
+
+ $instance->get( 'test', $fake, 'FOO' );
+ }
+
+ public function testAdd() {
+
+ $fake = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'runService' ] )
+ ->getMock();
+
+ $fake->expects( $this->once() )
+ ->method( 'runService' );
+
+ $instance = new ServicesContainer();
+
+ $instance->add( 'test', [ $this, 'fakeService' ] );
+ $instance->get( 'test', $fake );
+ }
+
+ public function testAddClosure() {
+
+ $fake = $this->getMockBuilder( '\stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'runService' ] )
+ ->getMock();
+
+ $fake->expects( $this->once() )
+ ->method( 'runService' );
+
+ $instance = new ServicesContainer();
+
+ $closure = function( $arg ) use( $fake ) {
+ $fake->runService( $arg );
+ };
+
+ $instance->add( 'test', $closure );
+ $instance->get( 'test', $fake );
+ }
+
+ public function testUnknownServiceThrowsException() {
+
+ $instance = new ServicesContainer();
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->get( 'test' );
+ }
+
+ public function testNonCallableServiceThrowsException() {
+
+ $instance = new ServicesContainer(
+ [
+ 'test' => 'Foo'
+ ]
+ );
+
+ $this->setExpectedException( '\RuntimeException' );
+ $instance->get( 'test' );
+ }
+
+ public function fakeService( $fake, $arg = '' ) {
+ $fake->runService( $arg );
+ }
+
+ public function stdClassService( $arg = '' ) {
+ return new \stdClass();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/SharedServicesContainerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/SharedServicesContainerTest.php
new file mode 100644
index 00000000..b4758e72
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Services/SharedServicesContainerTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace SMW\Tests\Services;
+
+use SMW\Services\SharedServicesContainer;
+
+/**
+ * @covers \SMW\Services\SharedServicesContainer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.3
+ *
+ * @author mwjames
+ */
+class SharedServicesContainerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SharedServicesContainer::class,
+ new SharedServicesContainer()
+ );
+
+ $this->assertInstanceOf(
+ '\Onoi\CallbackContainer\CallbackContainer',
+ new SharedServicesContainer()
+ );
+ }
+
+ public function testRegister() {
+
+ $containerBuilder = $this->getMockBuilder( '\Onoi\CallbackContainer\ContainerBuilder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $containerBuilder->expects( $this->atLeastOnce() )
+ ->method( 'registerCallback' );
+
+ $instance = new SharedServicesContainer();
+ $instance->register( $containerBuilder );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SiteTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SiteTest.php
new file mode 100644
index 00000000..ea8ac112
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/SiteTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Site;
+
+/**
+ * @covers \SMW\Site
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class SiteTest extends \PHPUnit_Framework_TestCase {
+
+ public function testIsReadOnly() {
+
+ $this->assertInternalType(
+ 'boolean',
+ Site::isReadOnly()
+ );
+ }
+
+ public function testIsBlocked() {
+
+ $this->assertInternalType(
+ 'boolean',
+ Site::isBlocked()
+ );
+ }
+
+ public function testName() {
+
+ $this->assertInternalType(
+ 'string',
+ Site::name()
+ );
+ }
+
+ public function testWikiurl() {
+
+ $this->assertInternalType(
+ 'string',
+ Site::wikiurl()
+ );
+ }
+
+ public function testLanguageCode() {
+
+ $this->assertInternalType(
+ 'string',
+ Site::languageCode()
+ );
+ }
+
+ public function testIsCommandLineMode() {
+
+ $this->assertInternalType(
+ 'boolean',
+ Site::isCommandLineMode()
+ );
+ }
+
+ public function testIsCapitalLinks() {
+
+ $this->assertInternalType(
+ 'boolean',
+ Site::isCapitalLinks()
+ );
+ }
+
+ public function testStats() {
+
+ $this->assertInternalType(
+ 'array',
+ Site::stats()
+ );
+ }
+
+ public function testGetJobClasses() {
+
+ $this->assertInternalType(
+ 'array',
+ Site::getJobClasses()
+ );
+
+ $this->assertNotEmpty(
+ Site::getJobClasses( 'SMW' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StoreTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StoreTest.php
new file mode 100644
index 00000000..def0c4c5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StoreTest.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIWikiPage;
+
+/**
+ * @covers \SMW\Store
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class StoreTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGetRedirectTarget() {
+
+ $wikipage = new DIWikiPage( 'Foo', NS_MAIN );
+ $expected = new DIWikiPage( 'Bar', NS_MAIN );
+
+ $instance = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getPropertyValues' ] )
+ ->getMockForAbstractClass();
+
+ $instance->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ $expected ] ) );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getRedirectTarget( $wikipage )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StringConditionTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StringConditionTest.php
new file mode 100644
index 00000000..84e45137
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/StringConditionTest.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\StringCondition;
+
+/**
+ * @covers \SMW\StringCondition
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class StringConditionTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $instance = new StringCondition( 'Foo', StringCondition::STRCOND_PRE, true );
+
+ $this->assertInstanceOf(
+ '\SMW\StringCondition',
+ $instance
+ );
+
+ $this->assertSame(
+ 'Foo',
+ $instance->string
+ );
+
+ $this->assertEquals(
+ 'Foo#0#1#',
+ $instance->getHash()
+ );
+
+ $this->assertEquals(
+ StringCondition::COND_PRE,
+ $instance->condition
+ );
+
+ $this->assertTrue(
+ $instance->isOr
+ );
+
+ $this->assertFalse(
+ $instance->isNot
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/TypesRegistryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/TypesRegistryTest.php
new file mode 100644
index 00000000..440e12db
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/TypesRegistryTest.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\TypesRegistry;
+
+/**
+ * @covers \SMW\TypesRegistry
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TypesRegistryTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGetDataTypeList() {
+
+ $this->assertInternalType(
+ 'array',
+ TypesRegistry::getDataTypeList()
+ );
+ }
+
+ public function testGetPropertyList() {
+
+ $this->assertInternalType(
+ 'array',
+ TypesRegistry::getPropertyList()
+ );
+ }
+
+ public function testGetFixedPropertyIdList() {
+
+ $propertyList = TypesRegistry::getPropertyList();
+
+ foreach ( TypesRegistry::getFixedPropertyIdList() as $key => $id ) {
+ $this->assertArrayHasKey( $key, $propertyList );
+ }
+ }
+
+ /**
+ * @dataProvider typeList
+ */
+ public function testTypeList_FirstCharUnderscore( $key, $def ) {
+ $this->assertTrue( $key{0} === '_' );
+ }
+
+ /**
+ * @dataProvider typeList
+ */
+ public function testTypeList_ClassExists( $key, $def ) {
+ $this->assertTrue( class_exists( $def[0] ) );
+ }
+
+ /**
+ * @dataProvider propertyList
+ */
+ public function testPropertyList_FirstCharUnderscore( $key, $def ) {
+ $this->assertTrue( $key{0} === '_' );
+ }
+
+ public function typeList() {
+
+ $excludes = [];
+
+ // Requires Maps/Semantic Maps hence remove from the
+ // test list
+ $excludes = [ '_geo', '_gpo' ];
+
+ foreach ( TypesRegistry::getDataTypeList() as $key => $def ) {
+
+ if ( in_array( $key, $excludes ) ) {
+ continue;
+ }
+
+ yield[ $key, $def ];
+ }
+ }
+
+ public function propertyList() {
+
+ $excludes = [];
+
+ foreach ( TypesRegistry::getPropertyList() as $key => $def ) {
+
+ if ( in_array( $key, $excludes ) ) {
+ continue;
+ }
+
+ yield[ $key, $def ];
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/BufferedStatsdCollectorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/BufferedStatsdCollectorTest.php
new file mode 100644
index 00000000..90508ad2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/BufferedStatsdCollectorTest.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use Onoi\BlobStore\BlobStore;
+use Onoi\BlobStore\Container;
+use SMW\Utils\BufferedStatsdCollector;
+
+/**
+ * @covers \SMW\Utils\BufferedStatsdCollector
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class BufferedStatsdCollectorTest extends \PHPUnit_Framework_TestCase {
+
+ private $blobStore;
+ private $container;
+
+ protected function setUp() {
+
+ $this->container = $this->getMockBuilder( Container::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore = $this->getMockBuilder( BlobStore::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->blobStore->expects( $this->any() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $this->container ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ BufferedStatsdCollector::class,
+ new BufferedStatsdCollector( $this->blobStore, 42 )
+ );
+ }
+
+ public function testIncr() {
+
+ $this->container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $this->container->expects( $this->once() )
+ ->method( 'get' )
+ ->will( $this->returnValue( 10 ) );
+
+ $this->container->expects( $this->once() )
+ ->method( 'set' )
+ ->with(
+ $this->equalTo( 'Foo.bar' ),
+ $this->equalTo( 11 ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'save' );
+
+ $instance = new BufferedStatsdCollector(
+ $this->blobStore,
+ 42
+ );
+
+ $instance->incr( 'Foo.bar' );
+ $instance->saveStats();
+ }
+
+ public function testSet() {
+
+ $this->container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $this->container->expects( $this->once() )
+ ->method( 'get' )
+ ->will( $this->returnValue( 10 ) );
+
+ $this->container->expects( $this->once() )
+ ->method( 'set' )
+ ->with(
+ $this->equalTo( 'Foo.bar' ),
+ $this->equalTo( 10 ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'save' );
+
+ $instance = new BufferedStatsdCollector(
+ $this->blobStore,
+ 42
+ );
+
+ $instance->set( 'Foo.bar', 10 );
+ $instance->saveStats();
+ }
+
+ public function testCalcMedian() {
+
+ $this->container->expects( $this->once() )
+ ->method( 'has' )
+ ->will( $this->returnValue( true ) );
+
+ $this->container->expects( $this->once() )
+ ->method( 'get' )
+ ->will( $this->returnValue( 10 ) );
+
+ $this->container->expects( $this->once() )
+ ->method( 'set' )
+ ->with(
+ $this->equalTo( 'Foo.bar' ),
+ $this->equalTo( 7.5 ) );
+
+ $this->blobStore->expects( $this->once() )
+ ->method( 'save' );
+
+ $instance = new BufferedStatsdCollector(
+ $this->blobStore,
+ 42
+ );
+
+ $instance->calcMedian( 'Foo.bar', 5 );
+ $instance->saveStats();
+ }
+
+ public function testStats_Simple() {
+
+ $this->container->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue( [ 'Foo' => 1, 'Bar' => 1 ] ) );
+
+ $expected = [
+ 'Foo' => 1,
+ 'Bar' => 1
+ ];
+
+ $instance = new BufferedStatsdCollector(
+ $this->blobStore,
+ 42
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getStats()
+ );
+ }
+
+ public function testStats_SimpleHierarchy() {
+
+ $this->container->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue( [ 'Foo.foobar' => 1, 'Bar' => 1 ] ) );
+
+ $expected = [
+ 'Foo' => [ 'foobar' => 1 ],
+ 'Bar' => 1
+ ];
+
+ $instance = new BufferedStatsdCollector(
+ $this->blobStore,
+ 42
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getStats()
+ );
+ }
+
+ public function testStats_ExtendedHierarchy() {
+
+ $this->container->expects( $this->once() )
+ ->method( 'getData' )
+ ->will( $this->returnValue( [ 'Foo.foobar' => 5, 'Bar' => 1, 'Foo.foobar.baz' => 1 ] ) );
+
+ $expected = [
+ 'Foo' => [ 'foobar' => [ 5, 'baz' => 1 ] ],
+ 'Bar' => 1
+ ];
+
+ $instance = new BufferedStatsdCollector(
+ $this->blobStore,
+ 42
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getStats()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharArmorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharArmorTest.php
new file mode 100644
index 00000000..e2e4e8e8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharArmorTest.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\CharArmor;
+
+/**
+ * @covers \SMW\Utils\CharArmor
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CharArmorTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider invisibleControlCharactersProvider
+ */
+ public function testRemoveControlChars( $withControlChar, $expected ) {
+
+ $this->assertFalse(
+ $expected === $withControlChar
+ );
+
+ $this->assertEquals(
+ $expected,
+ CharArmor::removeControlChars( $withControlChar )
+ );
+ }
+
+ /**
+ * @dataProvider specialCharactersProvider
+ */
+ public function testRemoveSpecialChars( $withSpecialChar, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ CharArmor::removeSpecialChars( $withSpecialChar )
+ );
+ }
+
+ public function invisibleControlCharactersProvider() {
+
+ $provider[] = [
+ '[[Left-To-Right Mark::"‎"]]',
+ '[[Left-To-Right Mark::""]]'
+ ];
+
+ $provider[] = [
+ '[[Right-To-Left Mark::"â€"]]',
+ '[[Right-To-Left Mark::""]]'
+ ];
+
+ $provider[] = [
+ '[[Zero-Width​Space::"​"]]',
+ '[[Zero-WidthSpace::""]]'
+ ];
+
+ $provider[] = [
+ '[[Zero Width Non-Joiner::"‌"]]',
+ '[[Zero Width Non-Joiner::""]]'
+ ];
+
+ $provider[] = [
+ '[[Zero Width Joiner::"â€"]]',
+ '[[Zero Width Joiner::""]]'
+ ];
+
+ return $provider;
+ }
+
+ public function specialCharactersProvider() {
+
+ $provider[] = [
+ 'visible shy&shy;ness',
+ 'visible shyness'
+ ];
+
+ $provider[] = [
+ 'leftToRight&lrm;Mark',
+ 'leftToRightMark'
+ ];
+
+ $provider[] = [
+ '[[Figure Space::" "]]',
+ '[[Figure Space::" "]]'
+ ];
+
+ $provider[] = [
+ '[[En Quad::" "]]',
+ '[[En Quad::" "]]'
+ ];
+
+ $provider[] = [
+ '[[Hair Space::" "]]',
+ '[[Hair Space::" "]]'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharExaminerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharExaminerTest.php
new file mode 100644
index 00000000..16b0010a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CharExaminerTest.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\CharExaminer;
+
+/**
+ * @covers \SMW\Utils\CharExaminer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CharExaminerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testToContainKoreanCharacters() {
+ $this->assertTrue(
+ CharExaminer::contains( CharExaminer::HANGUL, '한국어 í…ìŠ¤íŠ¸ì˜ ì˜ˆ' )
+ );
+
+ $this->assertFalse(
+ CharExaminer::contains( CharExaminer::HAN, '한국어 í…ìŠ¤íŠ¸ì˜ ì˜ˆ' )
+ );
+ }
+
+ public function testToContainJapaneseCharacters() {
+
+ $this->assertTrue(
+ CharExaminer::contains( CharExaminer::LATIN, '脳ã®IQテスト' )
+ );
+
+ $this->assertTrue(
+ CharExaminer::contains( CharExaminer::HIRAGANA_KATAKANA, '脳ã®IQテスト' )
+ );
+
+ $this->assertTrue(
+ CharExaminer::contains( CharExaminer::HAN, '脳ã®IQテスト' )
+ );
+ }
+
+ public function testToContainChineseCharacters() {
+
+ $this->assertFalse(
+ CharExaminer::contains( CharExaminer::LATIN, 'æ‰å¯ä»¥è¿‡å…³' )
+ );
+
+ $this->assertTrue(
+ CharExaminer::contains( CharExaminer::CJK_UNIFIED, 'æ‰å¯ä»¥è¿‡å…³' )
+ );
+
+ $this->assertTrue(
+ CharExaminer::contains( CharExaminer::HAN, 'æ‰å¯ä»¥è¿‡å…³' )
+ );
+ }
+
+ public function testToContainCyrillic() {
+
+ $this->assertFalse(
+ CharExaminer::contains( CharExaminer::LATIN, 'Привет' )
+ );
+
+ $this->assertTrue(
+ CharExaminer::contains( CharExaminer::CYRILLIC, 'Привет' )
+ );
+ }
+
+ public function testToContainUnknownCharacters() {
+ $this->assertFalse(
+ CharExaminer::contains( 'Foo', 'é¿©' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CircularReferenceGuardTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CircularReferenceGuardTest.php
new file mode 100644
index 00000000..cb42486a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CircularReferenceGuardTest.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\CircularReferenceGuard;
+
+/**
+ * @covers \SMW\Utils\CircularReferenceGuard
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class CircularReferenceGuardTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\Utils\CircularReferenceGuard',
+ new CircularReferenceGuard()
+ );
+ }
+
+ public function testRoundtripForRegisteredNamespace() {
+
+ $instance = new CircularReferenceGuard( 'bar' );
+ $instance->setMaxRecursionDepth( 1 );
+
+ $this->assertEquals(
+ 0,
+ $instance->get( 'Foo' )
+ );
+
+ $instance->mark( 'Foo' );
+ $instance->mark( 'Foo' );
+
+ $this->assertEquals(
+ 2,
+ $instance->get( 'Foo' )
+ );
+
+ $this->assertTrue(
+ $instance->isCircular( 'Foo' )
+ );
+
+ $instance->unmark( 'Foo' );
+
+ $this->assertEquals(
+ 1,
+ $instance->get( 'Foo' )
+ );
+
+ $this->assertFalse(
+ $instance->isCircular( 'Foo' )
+ );
+
+ $instance->unmark( 'notBeenMarkedBefore' );
+ }
+
+ /**
+ * @depends testRoundtripForRegisteredNamespace
+ */
+ public function testVerifyRetainedReferenceFromPreviousInvocation() {
+
+ $instance = new CircularReferenceGuard( 'bar' );
+
+ $this->assertEquals(
+ 1,
+ $instance->get( 'Foo' )
+ );
+
+ $instance->reset( 'bar' );
+
+ $this->assertEquals(
+ 0,
+ $instance->get( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CsvTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CsvTest.php
new file mode 100644
index 00000000..92c9ce8b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/CsvTest.php
@@ -0,0 +1,227 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\Csv;
+
+/**
+ * @covers \SMW\Utils\Csv
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class CsvTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider rowsProvider
+ */
+ public function testConcatenate( $rows, $sep, $expected ) {
+
+ $instance = new Csv();
+
+ $this->assertEquals(
+ $expected,
+ $instance->merge( $rows, $sep )
+ );
+ }
+
+ /**
+ * @dataProvider makeProvider
+ */
+ public function testMake( $header, $rows, $sep, $show, $expected ) {
+
+ $instance = new Csv( $show );
+
+ $this->assertEquals(
+ $expected,
+ $instance->toString( $header, $rows, $sep )
+ );
+ }
+
+ public function testWithBOM() {
+
+ $header = [];
+ $rows = [
+ [ 'Foo', '1', '2', '3' ]
+ ];
+
+ $bom = ( chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) );
+
+ $instance = new Csv( false, true );
+
+ $this->assertEquals(
+ "{$bom}Foo,1,2,3\n",
+ $instance->toString( $header, $rows, ',' )
+ );
+ }
+
+ public function rowsProvider() {
+
+ // No change
+ yield [
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ ],
+ ',',
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ ]
+ ];
+
+ // Concatenate duplicate
+ yield [
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Foo', '1', '2', '3' ],
+ ],
+ ',',
+ [
+ [ 'Foo', '1', '2', '3' ]
+ ]
+ ];
+
+ // Concatenate column values
+ yield [
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Foo', '1', '2', '4' ],
+ ],
+ ',',
+ [
+ [ 'Foo', '1', '2', '3,4' ]
+ ]
+ ];
+
+ // Concatenate column values
+ yield [
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Foo', '1', '2', '3', '4' ],
+ ],
+ ',',
+ [
+ [ 'Foo', '1', '2', '3' ]
+ ]
+ ];
+
+ yield [
+ [
+ [ 'Foo', '1', '2', '3', '4' ],
+ [ 'Foo', '1', '2', '3' ],
+ ],
+ ',',
+ [
+ [ 'Foo', '1', '2', '3', '4' ]
+ ]
+ ];
+
+ yield [
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ [ 'Foo', '4', '5', '6' ],
+ [ 'Bar', 'A', 'B', 'C' ],
+ ],
+ ',',
+ [
+ [ 'Foo', '1,4', '2,5', '3,6' ],
+ [ 'Bar', '1,A', '2,B', '3,C' ]
+ ]
+ ];
+
+ yield [
+ [
+ [ 'Foo', '1', '2', '3;6;2' ],
+ [ 'Bar', '1', '2', '3' ],
+ [ 'Foo', '4', '5', '6' ],
+ [ 'Bar', 'A', 'B', 'C' ],
+ ],
+ ';',
+ [
+ [ 'Foo', '1;4', '2;5', '3;6;2' ],
+ [ 'Bar', '1;A', '2;B', '3;C' ]
+ ]
+ ];
+ }
+
+ public function makeProvider() {
+
+ // Without header
+ yield [
+ [],
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ ],
+ ',',
+ false,
+ "Foo,1,2,3\nBar,1,2,3\n"
+ ];
+
+ // Without header, multiple value assignment
+ yield [
+ [],
+ [
+ [ 'Foo', '1', '2', '3,4' ],
+ [ 'Bar', '1', '2', '3' ],
+ ],
+ ',',
+ false,
+ "Foo,1,2,\"3,4\"\nBar,1,2,3\n"
+ ];
+
+ // With header
+ yield [
+ [ 'H1', 'H2', 'H3', 'H4' ],
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ ],
+ ',',
+ false,
+ "H1,H2,H3,H4\nFoo,1,2,3\nBar,1,2,3\n"
+ ];
+
+ // With header
+ yield [
+ [ 'H1', 'H2', 'H3', 'H4' ],
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ ],
+ ',',
+ true,
+ "sep=,\nH1,H2,H3,H4\nFoo,1,2,3\nBar,1,2,3\n"
+ ];
+
+ // fputcsv ... delimiter must be a single character
+ yield [
+ [],
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ ],
+ ',..;',
+ false,
+ "Foo,1,2,3\nBar,1,2,3\n"
+ ];
+
+ // fputcsv ... delimiter must be a single character
+ yield [
+ [],
+ [
+ [ 'Foo', '1', '2', '3' ],
+ [ 'Bar', '1', '2', '3' ],
+ ],
+ '',
+ false,
+ "Foo,1,2,3\nBar,1,2,3\n"
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ErrorCodeFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ErrorCodeFormatterTest.php
new file mode 100644
index 00000000..41eee654
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ErrorCodeFormatterTest.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\ErrorCodeFormatter;
+
+/**
+ * @covers \SMW\Utils\ErrorCodeFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class ErrorCodeFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGetStringFromJsonErrorCode() {
+
+ $this->assertInternalType(
+ 'string',
+ ErrorCodeFormatter::getStringFromJsonErrorCode( 'Foo' )
+ );
+
+ $contents = json_decode( '{ Foo: Bar }' );
+
+ $this->assertInternalType(
+ 'string',
+ ErrorCodeFormatter::getStringFromJsonErrorCode( json_last_error() )
+ );
+ }
+
+ public function testGetMessageFromJsonErrorCode() {
+
+ $this->assertInternalType(
+ 'string',
+ ErrorCodeFormatter::getMessageFromJsonErrorCode( 'Foo' )
+ );
+
+ $contents = json_decode( '{ Foo: Bar }' );
+
+ $this->assertInternalType(
+ 'string',
+ ErrorCodeFormatter::getMessageFromJsonErrorCode( json_last_error() )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/FileTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/FileTest.php
new file mode 100644
index 00000000..636ba0a0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/FileTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\File;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Utils\File
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class FileTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $instance = new File();
+
+ $this->assertInstanceOf(
+ File::class,
+ $instance
+ );
+ }
+
+ public function testWrite_ThrowsException() {
+
+ $instance = new File();
+
+ $this->setExpectedException( '\SMW\Exception\FileNotWritableException' );
+ $instance->write( 'abc/Foo', '' );
+ }
+
+ public function testDir() {
+
+ $this->assertInternalType(
+ 'string',
+ File::dir( 'foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HmacSerializerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HmacSerializerTest.php
new file mode 100644
index 00000000..98c302a6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HmacSerializerTest.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\HmacSerializer;
+
+/**
+ * @covers \SMW\Utils\HmacSerializer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HmacSerializerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testEncodeWithDifferentKey() {
+
+ $instance = new HmacSerializer();
+
+ $data = [ 'Foo' ];
+
+ $this->assertNotSame(
+ $instance->encode( $data, 'abc' ),
+ $instance->encode( $data, 'def' )
+ );
+ }
+
+ public function testUDecodeUsingAnObject() {
+
+ $this->assertFalse(
+ HmacSerializer::decode( $this )
+ );
+ }
+
+ public function testRoundtripEncodeDecode() {
+
+ $instance = new HmacSerializer();
+
+ $data = [ 'Foo' ];
+
+ $this->assertEquals(
+ $data,
+ $instance->decode( $instance->encode( $data, 'def' ), 'def' )
+ );
+ }
+
+ public function testRoundtripEncodeDecodeWithDifferentKey() {
+
+ $instance = new HmacSerializer();
+
+ $data = [ 'Foo' ];
+
+ $result = $instance->decode(
+ $instance->encode( $data, 'def' ),
+ 'abc'
+ );
+
+ $this->assertNotEquals(
+ $data,
+ $result
+ );
+
+ $this->assertFalse(
+ $result
+ );
+ }
+
+ public function testSeralizeWithDifferentKey() {
+
+ $data = [ 'Foo' ];
+
+ $this->assertNotSame(
+ HmacSerializer::serialize( $data, 'abc' ),
+ HmacSerializer::serialize( $data, 'def' )
+ );
+ }
+
+ public function testUnseralizeUsingAnObject() {
+
+ $this->assertFalse(
+ HmacSerializer::unserialize( $this )
+ );
+ }
+
+ public function testRoundtripSerializeDeserialize() {
+
+ $instance = new HmacSerializer();
+
+ $data = [ 'Foo' ];
+
+ $this->assertEquals(
+ $data,
+ $instance->unserialize( $instance->serialize( $data, 'def' ), 'def' )
+ );
+ }
+
+ public function testRoundtripCompressUncompress() {
+
+ $instance = new HmacSerializer();
+
+ $data = [ 'Foo' ];
+
+ $this->assertEquals(
+ $data,
+ $instance->uncompress( $instance->compress( $data, 'def' ), 'def' )
+ );
+ }
+
+ public function testRoundtripSerializeDeserializeWithDifferentKey() {
+
+ $instance = new HmacSerializer();
+
+ $data = [ 'Foo' ];
+
+ $result = $instance->unserialize(
+ $instance->serialize( $data, 'def' ),
+ 'abc'
+ );
+
+ $this->assertNotEquals(
+ $data,
+ $result
+ );
+
+ $this->assertFalse(
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlColumnsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlColumnsTest.php
new file mode 100644
index 00000000..a7bd07a5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlColumnsTest.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace SMW\Test\Utils;
+
+use SMW\Utils\HtmlColumns;
+use SMW\Tests\Utils\UtilityFactory;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Utils\HtmlColumns
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlColumnListFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->stringValidator = UtilityFactory::getInstance()->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ HtmlColumns::class,
+ new HtmlColumns()
+ );
+ }
+
+ public function testUnknownTypeThrowsException() {
+
+ $instance = new HtmlColumns();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+
+ $instance->addContents(
+ [ 'Foo' ],
+ 'bar'
+ );
+ }
+
+ public function testDefaultColumnUnorderedList() {
+
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Ichi', 'Ni' ]
+ ],
+ HtmlColumns::INDX_CONTENT
+ );
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:100%;" dir="ltr">',
+ '<div class="smw-column-header">a</div><ul><li>Foo</li><li>Bar</li></ul>',
+ '<div class="smw-column-header">B</div><ul><li>Ichi</li><li>Ni</li></ul></div>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testTwoColumnUnorderedList() {
+
+ $listContinuesAbbrev = '...';
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Baz', 'Fom', 'Fin', 'Fum' ]
+ ],
+ HtmlColumns::INDX_CONTENT
+ );
+
+ $instance->setColumns( 2 );
+ $instance->setContinueAbbrev( $listContinuesAbbrev );
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">a</div>',
+ '<ul><li>Foo</li><li>Bar</li></ul>',
+ '<div class="smw-column-header">B</div><ul><li>Baz</li></ul></div> <!-- end column -->',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">B ' . $listContinuesAbbrev .'</div>',
+ '<ul start=4><li>Fom</li><li>Fin</li><li>Fum</li></ul></div> <!-- end column -->',
+ '<br style="clear: both;"/></div>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testThreeColumnUnorderedList() {
+
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Ichi', 'Ni' ]
+ ],
+ HtmlColumns::INDX_CONTENT
+ );
+
+ $instance->setColumns( 3 );
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:33%;" dir="ltr">',
+ '<div class="smw-column-header">a</div><ul><li>Foo</li><li>Bar</li></ul></div>',
+ '<div class="smw-column" style="width:33%;" dir="ltr">',
+ '<div class="smw-column-header">B</div><ul><li>Ichi</li><li>Ni</li></ul></div>'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testTwoColumnOrderedList() {
+
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'a' => [ 'Foo', 'Bar' ],
+ 'B' => [ 'Ichi', 'Ni' ]
+ ],
+ HtmlColumns::INDX_CONTENT
+ );
+
+ $instance->setColumns( 2 );
+ $instance->setListType( 'ol' );
+
+ $expected = [
+ '<div class="smw-columnlist-container" dir="ltr">',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">a</div><ol><li>Foo</li><li>Bar</li></ol></div> <!-- end column -->',
+ '<div class="smw-column" style="width:50%;" dir="ltr">',
+ '<div class="smw-column-header">B</div><ol><li>Ichi</li><li>Ni</li></ol></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testTwoColumnOrderedListNoHeader() {
+
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'Foo', 'Baz', 'Bar'
+ ],
+ HtmlColumns::LIST_CONTENT
+ );
+
+ $instance->setColumns( 2 );
+ $instance->setColumnListClass( 'foo-class' );
+ $instance->setColumnClass( 'bar-class' );
+ $instance->setListType( 'ul' );
+
+ $expected = [
+ '<div class="foo-class" dir="ltr">',
+ '<div class="bar-class" style="width:50%;" dir="ltr">',
+ '<ul start=1><li>Foo</li><li>Baz</li></ul></div> <!-- end column -->',
+ '<div class="bar-class" style="width:50%;" dir="ltr">',
+ '<ul start=3><li>Bar</li></ul></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testResponsiveColumnsToBeDeterminedByBrowser() {
+
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'Foo', 'Baz', 'Bar'
+ ],
+ HtmlColumns::LIST_CONTENT
+ );
+
+ $instance->setColumns( 2 );
+ $instance->setColumnListClass( 'foo-class' );
+ $instance->setColumnClass( 'bar-responsive' );
+ $instance->setListType( 'ul' );
+ $instance->isRTL( true );
+
+ $expected = [
+ '<div class="foo-class" dir="rtl"><div class="bar-responsive" style="width:100%;" dir="rtl">',
+ '<ul start=1><li>Foo</li><li>Baz</li><li>Bar</li></ul></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testItemListWithAttributes() {
+
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'Foo', 'Baz', 'Bar'
+ ],
+ HtmlColumns::LIST_CONTENT
+ );
+
+ $instance->setColumns( 2 );
+ $instance->setColumnListClass( 'foo-class' );
+ $instance->setColumnClass( 'bar-responsive' );
+ $instance->setListType( 'ul' );
+ $instance->isRTL( true );
+
+ $instance->setItemAttributes(
+ [
+ md5( 'Foo' ) => [
+ 'id' => 123
+ ],
+ md5( 'Bar' ) => 456
+ ]
+ );
+
+ $expected = [
+ '<div class="foo-class" dir="rtl"><div class="bar-responsive" style="width:100%;" dir="rtl">',
+ '<ul start=1><li id="123">Foo</li><li>Baz</li><li 0="456">Bar</li></ul></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+ public function testOListWithAttributes() {
+
+ $instance = new HtmlColumns();
+
+ $instance->addContents(
+ [
+ 'Foo', 'Baz', 'Bar'
+ ],
+ HtmlColumns::LIST_CONTENT
+ );
+
+ $instance->setColumns( 2 );
+ $instance->setColumnListClass( 'foo-class' );
+ $instance->setColumnClass( 'bar-responsive' );
+ $instance->setListType( 'ol', 'i' );
+ $instance->isRTL( true );
+
+ $instance->setItemAttributes(
+ [
+ md5( 'Foo' ) => [
+ 'id' => 123
+ ],
+ md5( 'Bar' ) => 456
+ ]
+ );
+
+ $expected = [
+ '<div class="foo-class" dir="rtl"><div class="bar-responsive" style="width:100%;" dir="rtl">',
+ '<ol type=i start=1><li id="123">Foo</li><li>Baz</li><li 0="456">Bar</li></ol></div> <!-- end column -->'
+ ];
+
+ $this->stringValidator->assertThatStringContains(
+ $expected,
+ $instance->getHtml()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlDivTableTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlDivTableTest.php
new file mode 100644
index 00000000..414d960b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlDivTableTest.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\HtmlDivTable;
+
+/**
+ * @covers \SMW\Utils\HtmlDivTable
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlDivTableTest extends \PHPUnit_Framework_TestCase {
+
+ public function testOpenClose() {
+
+ $this->assertEquals(
+ '<div class="smw-table"></div>',
+ HtmlDivTable::open() . HtmlDivTable::close()
+ );
+
+ $this->assertEquals(
+ HtmlDivTable::table(),
+ HtmlDivTable::open() . HtmlDivTable::close()
+ );
+ }
+
+ public function testHeader() {
+
+ $this->assertEquals(
+ '<div class="smw-table-header bar">foo</div>',
+ HtmlDivTable::header( 'foo', [ 'class' => 'bar' ] )
+ );
+ }
+
+ public function testBody() {
+
+ $this->assertEquals(
+ '<div class="smw-table-body bar">foo</div>',
+ HtmlDivTable::body( 'foo', [ 'class' => 'bar' ] )
+ );
+ }
+
+ public function testFooter() {
+
+ $this->assertEquals(
+ '<div class="smw-table-footer bar">foo</div>',
+ HtmlDivTable::footer( 'foo', [ 'class' => 'bar' ] )
+ );
+ }
+
+ public function testRow() {
+
+ $this->assertEquals(
+ '<div class="smw-table-row bar">foo</div>',
+ HtmlDivTable::row( 'foo', [ 'class' => 'bar' ] )
+ );
+ }
+
+ public function testCell() {
+
+ $this->assertEquals(
+ '<div class="smw-table-cell bar">foo</div>',
+ HtmlDivTable::cell( 'foo', [ 'class' => 'bar' ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlModalTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlModalTest.php
new file mode 100644
index 00000000..72401c73
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlModalTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\HtmlModal;
+
+/**
+ * @covers \SMW\Utils\HtmlModal
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlModalTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGetModules() {
+
+ $this->assertInternalType(
+ 'array',
+ HtmlModal::getModules()
+ );
+
+ $this->assertInternalType(
+ 'array',
+ HtmlModal::getModuleStyles()
+ );
+ }
+
+ public function testLink() {
+
+ $this->assertContains(
+ 'smw-modal-link',
+ HtmlModal::link( 'Foo' )
+ );
+ }
+
+ public function testModal() {
+
+ $this->assertContains(
+ 'smw-modal',
+ HtmlModal::modal( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTableTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTableTest.php
new file mode 100644
index 00000000..6be1347f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTableTest.php
@@ -0,0 +1,118 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Tests\TestEnvironment;
+use SMW\Utils\HtmlTable;
+
+/**
+ * @covers \SMW\Utils\HtmlTable
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlTableTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->stringValidator = TestEnvironment::newValidatorFactory()->newStringValidator();
+ }
+
+ public function testStandardTable_Cell_Row() {
+
+ $instance = new HtmlTable();
+
+ $instance->cell( 'Foo', [ 'rel' => 'some' ] );
+ $instance->row( [ 'class' => 'bar' ] );
+
+ $this->stringValidator->assertThatStringContains(
+ '<table><tr class="bar row-odd"><td rel="some">Foo</td></tr></table>',
+ $instance->table()
+ );
+ }
+
+ public function testStandardTable_Header_Cell_Row() {
+
+ $instance = new HtmlTable();
+
+ $instance->header( 'Foo ');
+ $instance->cell( 'Bar' );
+ $instance->row();
+
+ $this->stringValidator->assertThatStringContains(
+ '<table><th>Foo </th><tr class="row-odd"><td>Bar</td></tr></table>',
+ $instance->table()
+ );
+ }
+
+ public function testStandardTable_Header_Cell_Row_IsHtml() {
+
+ $instance = new HtmlTable();
+
+ $instance->header( 'Foo' );
+ $instance->cell( 'Bar' );
+ $instance->row();
+
+ $this->stringValidator->assertThatStringContains(
+ '<table><thead><th>Foo</th></thead><tbody><tr class="row-odd"><td>Bar</td></tr></tbody></table>',
+ $instance->table( [], false, true )
+ );
+ }
+
+ public function testTransposedTable_Cell_Row() {
+
+ $instance = new HtmlTable();
+
+ // We need a dedicated header definition to support a table transpose
+ $instance->header( 'Foo' );
+ $instance->header( 'Bar' );
+
+ $instance->cell( 'lala', [ 'class' => 'foo' ] );
+ $instance->row();
+
+ $instance->cell( 'lula', [ 'rel' => 'tuuu' ] );
+ $instance->cell( 'lila' );
+ $instance->row();
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ '<table data-transpose="1"><tr class="row-odd"><th>Foo</th>',
+ '<td class="foo">lala</td><td rel="tuuu">lula</td></tr><tr class="row-even"><th>Bar</th>',
+ '<td></td><td>lila</td></tr></table>'
+ ],
+ $instance->table( [], true )
+ );
+ }
+
+ public function testTransposedTable_Cell_Row_IsHtml() {
+
+ $instance = new HtmlTable();
+
+ // We need a dedicated header definition to support a table transpose
+ $instance->header( 'Foo' );
+ $instance->header( 'Bar' );
+
+ $instance->cell( 'lala', [ 'class' => 'foo' ] );
+ $instance->row();
+
+ $instance->cell( 'lula', [ 'rel' => 'tuuu' ] );
+ $instance->cell( 'lila' );
+ $instance->row();
+
+ $this->stringValidator->assertThatStringContains(
+ [
+ '<table data-transpose="1"><tbody><tr class="row-odd"><th>Foo</th><td class="foo">lala</td>',
+ '<td rel="tuuu">lula</td></tr><tr class="row-even"><th>Bar</th><td></td><td>lila</td></tr>',
+ '</tbody></table>'
+ ],
+ $instance->table( [], true, true )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTabsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTabsTest.php
new file mode 100644
index 00000000..89b01450
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlTabsTest.php
@@ -0,0 +1,78 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\HtmlTabs;
+
+/**
+ * @covers \SMW\Utils\HtmlTabs
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlTabsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testTab_Contents() {
+
+ $instance = new HtmlTabs();
+ $instance->setActiveTab( 'foo' );
+ $instance->tab( 'foo', 'FOO' );
+ $instance->content( 'foo', '< ... bar ... >' );
+
+ $this->assertContains(
+ '<div class="smw-tabs foo-bar">' .
+ '<input id="tab-foo" class="nav-tab" type="radio" name="tabs" checked=""/>' .
+ '<label id="tab-label-foo" for="tab-foo" class="nav-label">FOO</label>' .
+ '<section id="tab-content-foo">< ... bar ... ></section>'.
+ '</div>',
+ $instance->buildHTML( [ 'class' => 'foo-bar' ] )
+ );
+ }
+
+ public function testTab_Contents_AutoChecked() {
+
+ $instance = new HtmlTabs();
+ $instance->tab( 'foo', 'FOO' );
+ $instance->content( 'foo', '< ... bar ... >' );
+
+ $this->assertContains(
+ '<div class="smw-tabs foo-bar">' .
+ '<input id="tab-foo" class="nav-tab" type="radio" name="tabs" checked=""/>' .
+ '<label id="tab-label-foo" for="tab-foo" class="nav-label">FOO</label>' .
+ '<section id="tab-content-foo">< ... bar ... ></section>'.
+ '</div>',
+ $instance->buildHTML( [ 'class' => 'foo-bar' ] )
+ );
+ }
+
+ public function testTab_Contents_Hidden() {
+
+ $instance = new HtmlTabs();
+
+ $instance->tab( 'foo', 'FOO', [ 'hide' => true ] );
+ $instance->content( 'foo', '< ... bar ... >' );
+
+ $this->assertContains(
+ '<div class="smw-tabs foo-bar"></div>',
+ $instance->buildHTML( [ 'class' => 'foo-bar' ] )
+ );
+ }
+
+ public function testTab_WithExtraHtml() {
+
+ $instance = new HtmlTabs();
+
+ $instance->tab( 'foo', 'FOO' );
+ $instance->content( 'foo', '< ... bar ... >' );
+ $instance->html( '<span>Foobar</span>' );
+
+ $this->assertContains(
+ '<span>Foobar</span>',
+ $instance->buildHTML()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlVTabsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlVTabsTest.php
new file mode 100644
index 00000000..13d425a6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/HtmlVTabsTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\HtmlVTabs;
+
+/**
+ * @covers \SMW\Utils\HtmlVTabs
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class HtmlVTabsTest extends \PHPUnit_Framework_TestCase {
+
+ protected function setUp() {
+ HtmlVTabs::init();
+ }
+
+ public function testGetModules() {
+
+ $this->assertInternalType(
+ 'array',
+ HtmlVTabs::getModules()
+ );
+ }
+
+ public function testGetModuleStyles() {
+
+ $this->assertInternalType(
+ 'array',
+ HtmlVTabs::getModuleStyles()
+ );
+ }
+
+ public function testNav() {
+
+ $this->assertContains(
+ '<div class="smw-vtab-nav nav-right" data-foo="bar">FooHtml</div>',
+ HtmlVTabs::nav( 'FooHtml', [ 'data-foo' => 'bar' ] )
+ );
+ }
+
+ public function testActiveLink() {
+
+ $this->assertContains(
+ '<button id="vtab-item-tab-foo" class="smw-vtab-link nav-right active" data-baz="foobar" data-id="tab-foo" type="submit"><a href="#tab-foo">barLabel</a></button>',
+ HtmlVTabs::navLink( 'foo', 'barLabel', HtmlVTabs::IS_ACTIVE, [ 'data-baz' => 'foobar' ] )
+ );
+ }
+
+ public function testHiddenLink() {
+
+ $this->assertEmpty(
+ HtmlVTabs::navLink( 'foo', 'bar', HtmlVTabs::IS_HIDDEN, [ 'data-baz' => 'foobar' ] )
+ );
+ }
+
+ public function testFindActiveLink() {
+
+ $this->assertContains(
+ '<button id="vtab-item-tab-foo" class="smw-vtab-link nav-right active" data-baz="foobar" data-id="tab-foo" type="submit"><a href="#tab-foo">barLabel</a></button>',
+ HtmlVTabs::navLink( 'foo', 'barLabel', [ HtmlVTabs::FIND_ACTIVE_LINK => 'foo' ], [ 'data-baz' => 'foobar' ] )
+ );
+
+ $this->assertContains(
+ '<button id="vtab-item-tab-foo" class="smw-vtab-link nav-right" data-baz="foobar" data-id="tab-foo" type="submit"><a href="#tab-foo">barLabel</a></button>',
+ HtmlVTabs::navLink( 'foo', 'barLabel', [ HtmlVTabs::FIND_ACTIVE_LINK => 'bar' ], [ 'data-baz' => 'foobar' ] )
+ );
+ }
+
+ public function testLinkRight() {
+
+ $this->assertContains(
+ '<button id="vtab-item-tab-foo" class="smw-vtab-link nav-right" data-id="tab-foo" type="submit"><a href="#tab-foo">bar</a></button>',
+ HtmlVTabs::navLink( 'foo', 'bar' )
+ );
+ }
+
+ public function testLinkLeft() {
+
+ HtmlVTabs::setDirection( 'left' );
+
+ $this->assertContains(
+ '<button id="vtab-item-tab-foo" class="smw-vtab-link nav-left" data-id="tab-foo" type="submit"><a href="#tab-foo">bar</a></button>',
+ HtmlVTabs::navLink( 'foo', 'bar' )
+ );
+ }
+
+ public function testContentWithActiveDisplay() {
+
+ HtmlVTabs::navLink( 'foo', 'barLabel', HtmlVTabs::IS_ACTIVE );
+
+ $this->assertContains(
+ '<div id="tab-foo" class="smw-vtab-content" data-baz="foobar">bar</div>',
+ HtmlVTabs::content( 'foo', 'bar', [ 'data-baz' => 'foobar' ] )
+ );
+ }
+
+ public function testContentWithNoneDisplay() {
+
+ $this->assertContains(
+ '<div id="tab-foo2" class="smw-vtab-content" data-baz="foobar" style="display:none;">bar</div>',
+ HtmlVTabs::content( 'foo2', 'bar', [ 'data-baz' => 'foobar' ] )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ImageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ImageTest.php
new file mode 100644
index 00000000..87016967
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/ImageTest.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\Image;
+use SMW\DIWikiPage;
+
+/**
+ * @covers \SMW\Utils\Image
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ImageTest extends \PHPUnit_Framework_TestCase {
+
+ public function testIsImage() {
+
+ $this->assertTrue(
+ Image::isImage( DIWikiPage::newFromText( 'Foo.png', NS_FILE ) )
+ );
+
+ $this->assertTrue(
+ Image::isImage( DIWikiPage::newFromText( '一二三.png', NS_FILE ) )
+ );
+
+ $this->assertFalse(
+ Image::isImage( DIWikiPage::newFromText( 'Foo.png', NS_MAIN ) )
+ );
+
+ $this->assertFalse(
+ Image::isImage( DIWikiPage::newFromText( 'Foo', NS_FILE ) )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/JsonSchemaValidatorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/JsonSchemaValidatorTest.php
new file mode 100644
index 00000000..56de260e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/JsonSchemaValidatorTest.php
@@ -0,0 +1,121 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use JsonSchema\Exception\ResourceNotFoundException;
+use JsonSchema\Validator as SchemaValidator;
+use JsonSerializable;
+use SMW\ApplicationFactory;
+use SMW\Utils\JsonSchemaValidator;
+
+/**
+ * @covers \SMW\Utils\JsonSchemaValidator
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class JsonSchemaValidatorTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ JsonSchemaValidator::class,
+ new JsonSchemaValidator()
+ );
+
+ $applicationFactory = ApplicationFactory::getInstance();
+
+ $this->assertInstanceOf(
+ JsonSchemaValidator::class,
+ $applicationFactory->create( 'JsonSchemaValidator' )
+ );
+
+ $this->assertInstanceOf(
+ JsonSchemaValidator::class,
+ $applicationFactory->create( JsonSchemaValidator::class )
+ );
+ }
+
+ public function testNoSchemaValidator() {
+
+ $instance = new JsonSchemaValidator();
+
+ $this->assertFalse(
+ $instance->hasSchemaValidator()
+ );
+ }
+
+ public function testValidate() {
+
+ if ( !class_exists( SchemaValidator::class ) ) {
+ $this->markTestSkipped( 'JsonSchema\Validator is not available.' );
+ }
+
+ $data = $this->getMockBuilder( JsonSerializable::class )
+ ->setMethods( [ 'jsonSerialize' ] )
+ ->getMock();
+
+ $data->expects( $this->any() )
+ ->method( 'jsonSerialize' )
+ ->will( $this->returnValue( json_encode( [ 'Foo' ] ) ) );
+
+ $schemaValidator = $this->getMockBuilder( SchemaValidator::class )
+ ->setMethods( [ 'check' ] )
+ ->getMock();
+
+ $instance = new JsonSchemaValidator(
+ $schemaValidator
+ );
+
+ $instance->validate( $data, 'Foo' );
+
+ $this->assertTrue(
+ $instance->isValid()
+ );
+
+ $this->assertEmpty(
+ $instance->getErrors()
+ );
+ }
+
+ public function testValidateWhereSchemaValidatorThrowsException() {
+
+ if ( !class_exists( SchemaValidator::class ) ) {
+ $this->markTestSkipped( 'JsonSchema\Validator is not available.' );
+ }
+
+ $data = $this->getMockBuilder( JsonSerializable::class )
+ ->setMethods( [ 'jsonSerialize' ] )
+ ->getMock();
+
+ $data->expects( $this->any() )
+ ->method( 'jsonSerialize' )
+ ->will( $this->returnValue( json_encode( [ 'Foo' ] ) ) );
+
+ $schemaValidator = $this->getMockBuilder( SchemaValidator::class )
+ ->setMethods( [ 'check' ] )
+ ->getMock();
+
+ $schemaValidator->expects( $this->any() )
+ ->method( 'check' )
+ ->will($this->throwException( new ResourceNotFoundException() ) );
+
+ $instance = new JsonSchemaValidator(
+ $schemaValidator
+ );
+
+ $instance->validate( $data, 'Foo' );
+
+ $this->assertFalse(
+ $instance->isValid()
+ );
+
+ $this->assertNotEmpty(
+ $instance->getErrors()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LoggerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LoggerTest.php
new file mode 100644
index 00000000..a2c436d6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LoggerTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\Logger;
+
+/**
+ * @covers \SMW\Utils\Logger
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class LoggerTest extends \PHPUnit_Framework_TestCase {
+
+ private $logger;
+
+ protected function setUp() {
+
+ $this->logger = $this->getMockBuilder( '\Psr\Log\LoggerInterface' )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ Logger::class,
+ new Logger( $this->logger )
+ );
+ }
+
+ /**
+ * @dataProvider logProvider
+ */
+ public function testLog( $role, $message, $context ) {
+
+ $this->logger->expects( $this->once() )
+ ->method( 'log' );
+
+ $instance = new Logger( $this->logger, $role );
+ $instance->log( 'Foo', $message, $context );
+ }
+
+ public function logProvider() {
+
+ yield [
+ Logger::ROLE_DEVELOPER,
+ 'Foo',
+ [ 'Foo' ]
+ ];
+
+ yield [
+ Logger::ROLE_DEVELOPER,
+ 'Foo',
+ [ 'Foo', [ 'Bar' => 123 ] ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LruTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LruTest.php
new file mode 100644
index 00000000..323a6f48
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/LruTest.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\Lru;
+
+/**
+ * @covers \SMW\Utils\Lru
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class LruTest extends \PHPUnit_Framework_TestCase {
+
+ public function testSetGet() {
+
+ $instance = new Lru( 3 );
+
+ $instance->set( 'a', 3 );
+ $instance->set( 'b', 'abc' );
+ $instance->set( 'c', 'def' );
+ $instance->set( 'd', 2 );
+
+ $this->assertEquals(
+ [
+ 'b' => 'abc',
+ 'c' => 'def',
+ 'd' => 2
+ ],
+ $instance->toArray()
+ );
+
+ $this->assertEquals(
+ 'def',
+ $instance->get( 'c' )
+ );
+
+ $instance->get( 'b' );
+ $instance->set( 'foo', 'bar' );
+
+ $this->assertEquals(
+ [
+ 'b' => 'abc',
+ 'c' => 'def',
+ 'foo' => 'bar'
+ ],
+ $instance->toArray()
+ );
+
+ $instance->get( 'c' );
+ $instance->get( 'foo' );
+ $instance->set( 'foobar', 'xyz' );
+
+ $this->assertEquals(
+ [
+ 'c' => 'def',
+ 'foo' => 'bar',
+ 'foobar' => 'xyz'
+ ],
+ $instance->toArray()
+ );
+ }
+
+ public function testDelete() {
+
+ $instance = new Lru( 3 );
+
+ $instance->set( 'a', 3 );
+ $instance->delete( 'a' );
+
+ $this->assertEquals(
+ [],
+ $instance->toArray()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/NormalizerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/NormalizerTest.php
new file mode 100644
index 00000000..f21b2858
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/NormalizerTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\Normalizer;
+
+/**
+ * @covers \SMW\Utils\Normalizer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class NormalizerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testReduceLengthTo() {
+
+ $this->assertEquals(
+ 'ABC',
+ Normalizer::reduceLengthTo( 'ABCDEF', 3 )
+ );
+
+ $this->assertEquals(
+ 'ABCDEF',
+ Normalizer::reduceLengthTo( 'ABCDEF' )
+ );
+
+ $this->assertEquals(
+ 'ABCD',
+ Normalizer::reduceLengthTo( 'ABCD EF', 4 )
+ );
+
+ $this->assertEquals(
+ 'ABC',
+ Normalizer::reduceLengthTo( 'ABC D EF', 4 )
+ );
+
+ $this->assertEquals(
+ 'ABCD',
+ Normalizer::reduceLengthTo( 'ABCD EF', 5 )
+ );
+
+ $this->assertEquals(
+ 'abc def gh',
+ Normalizer::reduceLengthTo( 'abc def gh in 123', 12 )
+ );
+ }
+
+ public function testToLowercase() {
+
+ $this->assertEquals(
+ 'abcdef',
+ Normalizer::toLowercase( 'ABCDEF' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/StatsFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/StatsFormatterTest.php
new file mode 100644
index 00000000..b5ead42a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/StatsFormatterTest.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\StatsFormatter;
+
+/**
+ * @covers \SMW\Utils\StatsFormatter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class StatsFormatterTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider statsProvider
+ */
+ public function testGetStatsFromFlatKey( $stats, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ StatsFormatter::getStatsFromFlatKey( $stats )
+ );
+ }
+
+ /**
+ * @dataProvider formatProvider
+ */
+ public function testFormat( $stats, $format, $expected ) {
+
+ $this->assertInternalType(
+ $expected,
+ StatsFormatter::format( $stats, $format )
+ );
+ }
+
+ public function formatProvider() {
+
+ $provider[] = [
+ [ 'Foo' => 1, 'Bar' => 1 ],
+ StatsFormatter::FORMAT_PLAIN,
+ 'string'
+ ];
+
+ $provider[] = [
+ [ 'Foo' => 1, 'Bar' => 1 ],
+ StatsFormatter::FORMAT_HTML,
+ 'string'
+ ];
+
+ $provider[] = [
+ [ 'Foo' => 1, 'Bar' => 1 ],
+ StatsFormatter::FORMAT_JSON,
+ 'string'
+ ];
+
+ $provider[] = [
+ [ 'Foo' => 1, 'Bar' => 1 ],
+ null,
+ 'array'
+ ];
+
+ return $provider;
+ }
+
+ public function statsProvider() {
+
+ $provider[] = [
+ [ 'Foo' => 1, 'Bar' => 1 ],
+ [
+ 'Foo' => 1,
+ 'Bar' => 1
+ ]
+ ];
+
+ $provider[] = [
+ [ 'Foo.foobar' => 1, 'Bar' => 1 ],
+ [
+ 'Foo' => [ 'foobar' => 1 ],
+ 'Bar' => 1
+ ]
+ ];
+
+ $provider[] = [
+ [ 'Foo.foobar' => 5, 'Bar' => 1, 'Foo.foobar.baz' => 1 ],
+ [
+ 'Foo' => [ 'foobar' => [ 5, 'baz' => 1 ] ],
+ 'Bar' => 1
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TempFileTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TempFileTest.php
new file mode 100644
index 00000000..b29fa1bf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TempFileTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\TempFile;
+
+/**
+ * @covers \SMW\Utils\TempFile
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class TempFileTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGenerate() {
+
+ $instance = new TempFile();
+
+ $this->assertContains(
+ '6na5ojj24og0',
+ $instance->generate( 'Foo' )
+ );
+
+ $this->assertContains(
+ 'Bar7vmi67tsvkb0',
+ $instance->generate( 'Bar', 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TimerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TimerTest.php
new file mode 100644
index 00000000..41e7ca30
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TimerTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\Timer;
+
+/**
+ * @covers \SMW\Utils\Timer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TimerTest extends \PHPUnit_Framework_TestCase {
+
+ public function testGetElapsedTime() {
+
+ Timer::start( __CLASS__ );
+
+ $this->assertInternalType(
+ 'float',
+ Timer::getElapsedTime( __CLASS__ )
+ );
+
+ $this->assertInternalType(
+ 'float',
+ Timer::getElapsedTime( __CLASS__, 5 )
+ );
+ }
+
+ public function testGetElapsedTimeWithoutStart() {
+
+ $this->assertEquals(
+ 0,
+ Timer::getElapsedTime( 'Foo' )
+ );
+ }
+
+ public function testGetElapsedTimeAsLoggableMessage() {
+
+ $this->assertInternalType(
+ 'string',
+ Timer::getElapsedTimeAsLoggableMessage( 'Foo' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TokenizerTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TokenizerTest.php
new file mode 100644
index 00000000..d9f12a2f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Unit/Utils/TokenizerTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\Utils\Tokenizer;
+
+/**
+ * @covers \SMW\Utils\Tokenizer
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class TokenizerTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider textProvider
+ */
+ public function testTokenize( $text, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ Tokenizer::tokenize( $text )
+ );
+ }
+
+ public function textProvider() {
+
+ $provider[] = [
+ 'foo',
+ [ 'foo' ]
+ ];
+
+ $provider[] = [
+ 'foo bar',
+ [ 'foo', 'bar' ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ByPageSemanticDataFinder.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ByPageSemanticDataFinder.php
new file mode 100644
index 00000000..61bb4225
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ByPageSemanticDataFinder.php
@@ -0,0 +1,144 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use ParserOutput;
+use SMW\ParserData;
+use SMW\SemanticData;
+use SMW\Store;
+use Title;
+use UnexpectedValueException;
+use User;
+use WikiPage;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class ByPageSemanticDataFinder {
+
+ protected $store = null;
+ protected $title = null;
+
+ /**
+ * @since 1.9.1
+ *
+ * @param Store $store
+ *
+ * @return PageDataFetcher
+ */
+ public function setStore( Store $store ) {
+ $this->store = $store;
+ return $this;
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param Title $title
+ *
+ * @return PageDataFetcher
+ */
+ public function setTitle( Title $title ) {
+ $this->title = $title;
+ return $this;
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @return SemanticData
+ */
+ public function fetchIncomingDataFromStore() {
+
+ $requestOptions = new \SMWRequestOptions();
+ $requestOptions->sort = true;
+
+ $subject = $this->getPageData()->getSubject();
+ $semanticData = new SemanticData( $subject );
+
+ $incomingProperties = $this->getStore()->getInProperties( $subject, $requestOptions );
+
+ foreach ( $incomingProperties as $property ) {
+ $values = $this->getStore()->getPropertySubjects( $property, null );
+
+ foreach ( $values as $value ) {
+ $semanticData->addPropertyObjectValue( $property, $value );
+ }
+ }
+
+ return $semanticData;
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @return SemanticData
+ */
+ public function fetchFromStore() {
+ return $this->getStore()->getSemanticData( $this->getPageData()->getSubject() );
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @return SemanticData
+ */
+ public function fetchFromOutput() {
+ return $this->getPageData()->getData();
+ }
+
+ protected function getPageData() {
+ return new ParserData( $this->getTitle(), $this->makeOutputFromPageRevision() );
+ }
+
+ protected function getPage() {
+ return WikiPage::factory( $this->getTitle() );
+ }
+
+ protected function makeOutputFromPageRevision() {
+
+ $wikiPage = $this->getPage();
+ $revision = $wikiPage->getRevision();
+
+ if ( $revision === null ) {
+ throw new UnexpectedValueException( 'Expected a valid Revision' );
+ }
+
+ $parserOutput = $wikiPage->getParserOutput(
+ $wikiPage->makeParserOptions( User::newFromId( $revision->getUser() ) ),
+ $revision->getId()
+ );
+
+ if ( $parserOutput instanceof ParserOutput ) {
+ return $parserOutput;
+ }
+
+ throw new UnexpectedValueException( 'Expected a ParserOutput object' );
+ }
+
+ protected function getTitle() {
+
+ if ( $this->title instanceof Title ) {
+ return $this->title;
+ }
+
+ throw new UnexpectedValueException( 'Expected a Title object' );
+ }
+
+ protected function getStore() {
+
+ if ( $this->store instanceof Store ) {
+ return $this->store;
+ }
+
+ throw new UnexpectedValueException( 'Expected a Store object' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/ConnectionProvider.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/ConnectionProvider.php
new file mode 100644
index 00000000..07efd732
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/ConnectionProvider.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace SMW\Tests\Utils\Connection;
+
+use DatabaseBase;
+use SMW\Connection\ConnectionProvider as IConnectionProvider;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ConnectionProvider implements IConnectionProvider {
+
+ /**
+ * @var DatabaseBase
+ */
+ protected $connection;
+
+ protected $id;
+
+ /**
+ * @since 2.0
+ *
+ * @param int $id
+ */
+ public function __construct( $id = DB_MASTER ) {
+ $this->id = $id;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return DatabaseBase
+ */
+ public function getConnection() {
+
+ if ( $this->connection === null ) {
+ $this->connection = wfGetDB( $this->id );
+ }
+
+ return $this->connection;
+ }
+
+ public function releaseConnection() {
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/TestDatabaseTableBuilder.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/TestDatabaseTableBuilder.php
new file mode 100644
index 00000000..a68222e1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Connection/TestDatabaseTableBuilder.php
@@ -0,0 +1,297 @@
+<?php
+
+namespace SMW\Tests\Utils\Connection;
+
+use CloneDatabase;
+use HashBagOStuff;
+use ObjectCache;
+use RuntimeException;
+use SMW\Connection\ConnectionProvider as IConnectionProvider;
+use SMW\Tests\Utils\PageCreator;
+use SMW\Store;
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class TestDatabaseTableBuilder {
+
+ /**
+ * @var TestDatabaseTableBuilder
+ */
+ private static $instance = null;
+
+ /**
+ * @var Store
+ */
+ protected $store;
+
+ /**
+ * @var IConnectionProvider
+ */
+ protected $connectionProvider;
+
+ /**
+ * @var CloneDatabase
+ */
+ protected $cloneDatabase;
+
+ protected $supportedDatabaseTypes = [
+ 'mysql',
+ 'sqlite',
+ 'postgres'
+ ];
+
+ protected $availableDatabaseTypes = [];
+
+ private static $UTDB_PREFIX = null;
+ private static $MWDB_PREFIX = null;
+
+ private $dbSetup = false;
+
+ /**
+ * @since 2.0
+ *
+ * @param Store $store
+ * @param IConnectionProvider $connectionProvider
+ */
+ public function __construct( Store $store, IConnectionProvider $connectionProvider ) {
+ $this->store = $store;
+ $this->connectionProvider = $connectionProvider;
+ $this->availableDatabaseTypes = $this->supportedDatabaseTypes;
+
+ self::$UTDB_PREFIX = 'sunittest_';
+ self::$MWDB_PREFIX = $GLOBALS['wgDBprefix'];
+
+ // MediaWikiTestCase changes the GLOBAL state therefore
+ // we have to ensure that we really use the original DB and
+ // not an existing 'unittest_' created by a MW test
+ if ( self::$MWDB_PREFIX === 'unittest_' ) {
+ self::$MWDB_PREFIX = '';
+ }
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param Store $store
+ *
+ * @return self
+ */
+ public static function getInstance( Store $store ) {
+
+ if ( self::$instance === null ) {
+ self::$instance = new self( $store, new ConnectionProvider() );
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param string|null $databaseType
+ *
+ * @return self
+ */
+ public function removeAvailableDatabaseType( $databaseType = null ) {
+ $this->availableDatabaseTypes = array_diff( $this->supportedDatabaseTypes, (array)$databaseType );
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @throws RuntimeException
+ */
+ public function doBuild() {
+
+ if ( !$this->isAvailableDatabaseType() ) {
+ throw new RuntimeException( 'Requested DB type is not available through this installer' );
+ }
+
+ ObjectCache::$instances[CACHE_DB] = new HashBagOStuff();
+
+ // Avoid Error while sending QUERY packet / SqlBagOStuff seen on MW 1.24
+ // https://s3.amazonaws.com/archive.travis-ci.org/jobs/30408638/log.txt
+ ObjectCache::$instances[CACHE_ANYTHING] = new HashBagOStuff();
+
+ $GLOBALS['wgDevelopmentWarnings'] = true;
+ $GLOBALS['wgMainCacheType'] = CACHE_NONE;
+ $GLOBALS['wgMessageCacheType'] = CACHE_NONE;
+ $GLOBALS['wgParserCacheType'] = CACHE_NONE;
+ $GLOBALS['wgLanguageConverterCacheType'] = CACHE_NONE;
+ $GLOBALS['wgUseDatabaseMessages'] = false;
+
+ $this->setupDatabaseTables();
+ $this->rollbackOpenDatabaseTransactions();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public function doDestroy() {
+ $this->destroyDatabaseTables();
+ $this->rollbackOpenDatabaseTransactions();
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return string
+ */
+ public function getDBPrefix() {
+ return self::$UTDB_PREFIX;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return DatabaseBase
+ */
+ public function getDBConnection() {
+ return $this->connectionProvider->getConnection();
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return ConnectionProvider
+ */
+ public function getConnectionProvider() {
+ return $this->connectionProvider;
+ }
+
+ /**
+ * @see MediaWikiTestCase::listTables
+ */
+ protected function generateListOfTables() {
+
+ $dbConnection = $this->getDBConnection();
+
+ $tables = $dbConnection->listTables(
+ self::$MWDB_PREFIX,
+ __METHOD__
+ );
+
+ if ( $dbConnection->getType() === 'mysql' && method_exists( $dbConnection, 'listViews' ) ) {
+
+ # bug 43571: cannot clone VIEWs under MySQL
+ $views = $dbConnection->listViews(
+ self::$MWDB_PREFIX,
+ __METHOD__
+ );
+
+ $tables = array_diff( $tables, $views );
+ }
+
+ $tables = array_map( [ $this, 'unprefixTable' ], $tables );
+
+ // Don't duplicate test tables from the previous failed run
+ $tables = array_filter( $tables, [ $this, 'isNotUnittest' ] );
+
+ // @see MediaWikiTestCase::listTables
+ if ( $dbConnection->getType() === 'sqlite' ) {
+ $tables = array_filter( $tables, [ $this, 'isNotSearchindex' ] );
+ }
+
+ return $tables;
+ }
+
+ private function setupDatabaseTables() {
+
+ if ( $this->dbSetup ) {
+ return true;
+ }
+
+ $this->cloneDatabaseTables();
+ $this->store->setup( false );
+ $this->createDummyPage();
+
+ $this->dbSetup = true;
+ }
+
+ private function cloneDatabaseTables() {
+
+ $tablesToBeCloned = $this->generateListOfTables();
+
+ // MW's DatabaseSqlite does some magic on its own therefore
+ // we force our way
+ if ( $this->getDBConnection()->getType() === 'sqlite' ) {
+ CloneDatabase::changePrefix( self::$MWDB_PREFIX );
+ }
+
+ $this->cloneDatabase = new CloneDatabase(
+ $this->getDBConnection(),
+ $tablesToBeCloned,
+ $this->getDBPrefix()
+ );
+
+ // Ensure no leftovers
+ if ( $this->getDBConnection()->getType() === 'postgres' ) {
+ $this->cloneDatabase->destroy( true );
+ }
+
+ // Rebuild the DB (in order to exclude temporary table usage)
+ // otherwise some tests will fail with
+ // "Error: 1137 Can't reopen table" on MySQL (see Issue #80)
+ $this->cloneDatabase->useTemporaryTables( false );
+ $this->cloneDatabase->cloneTableStructure();
+
+ // #3197
+ // @see https://github.com/wikimedia/mediawiki/commit/6badc7415684df54d6672098834359223b859507
+ CloneDatabase::changePrefix( self::$UTDB_PREFIX );
+ }
+
+ private function createDummyPage() {
+
+ $pageCreator = new PageCreator();
+ $pageCreator
+ ->createPage( Title::newFromText( 'SMWUTDummyPage' ) )
+ ->doEdit( 'SMW dummy page' );
+ }
+
+ private function destroyDatabaseTables() {
+
+ if ( !$this->cloneDatabase instanceof CloneDatabase ) {
+ throw new RuntimeException( 'CloneDatabase instance is missing, unable to destory the database tables' );
+ }
+
+ $this->cloneDatabase->destroy( true );
+ $this->availableDatabaseTypes = $this->supportedDatabaseTypes;
+ $this->dbSetup = false;
+ }
+
+ private function rollbackOpenDatabaseTransactions() {
+
+ if ( $this->getDBConnection() ) {
+
+ while ( $this->getDBConnection()->trxLevel() > 0 ) {
+ $this->getDBConnection()->rollback();
+ }
+
+ // 1.26 was mde protected
+ // $this->getDBConnection()->ignoreErrors( false );
+ }
+ }
+
+ private function unprefixTable( $tableName ) {
+ return substr( $tableName, strlen( self::$MWDB_PREFIX ) );
+ }
+
+ private function isNotUnittest( $table ) {
+ return strpos( $table, 'unittest_' ) === false && strpos( $table, 'sunittest_' ) === false;
+ }
+
+ private function isNotSearchindex( $table ) {
+ return strpos( $table, 'searchindex' ) === false && strpos( $table, 'smw_ft_search' ) === false;
+ }
+
+ private function isAvailableDatabaseType() {
+ return in_array( $this->getDBConnection()->getType(), $this->availableDatabaseTypes );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/BulkFileProvider.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/BulkFileProvider.php
new file mode 100644
index 00000000..22dfded9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/BulkFileProvider.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace SMW\Tests\Utils\File;
+
+use RuntimeException;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class BulkFileProvider {
+
+ /**
+ * @var string
+ */
+ private $path = null;
+
+ /**
+ * @var string
+ */
+ private $extension = 'json';
+
+ /**
+ * @since 2.1
+ *
+ * @param string $path
+ */
+ public function __construct( $path ) {
+ $this->path = $path;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $extension
+ */
+ public function searchByFileExtension( $extension ) {
+ $this->extension = $extension;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return array
+ */
+ public function getFiles() {
+
+ $path = $this->checkPathReadability( $this->path );
+
+ return $this->iterateToFindFilesForExtension(
+ $path,
+ $this->extension
+ );
+ }
+
+ private function checkPathReadability( $path ) {
+
+ $path = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $path );
+
+ if ( is_readable( $path ) ) {
+ return $path;
+ }
+
+ throw new RuntimeException( "Expected an accessible {$path} path" );
+ }
+
+ private function iterateToFindFilesForExtension( $path, $extension ) {
+
+ $files = [];
+
+ $directoryIterator = new \RecursiveDirectoryIterator( $path );
+
+ foreach ( new \RecursiveIteratorIterator( $directoryIterator ) as $fileInfo ) {
+ if ( strtolower( substr( $fileInfo->getFilename(), -( strlen( $extension ) + 1 ) ) ) === ( '.' . $extension ) ) {
+
+ // Use a shortcut to be sortable while keep files with same name
+ // in different directories distinct
+ $files[$fileInfo->getFilename() . ' (' . substr( md5( $fileInfo->getPathname() ), 0, 5 ) .')'] = $fileInfo->getPathname();
+ }
+ }
+
+ asort( $files );
+
+ return $files;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/ContentsReader.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/ContentsReader.php
new file mode 100644
index 00000000..a9ac8a37
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/ContentsReader.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace SMW\Tests\Utils\File;
+
+use RuntimeException;
+
+/**
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author mwjames
+ */
+class ContentsReader {
+
+ /**
+ * @since 3.0
+ *
+ * @param string $file
+ *
+ * @return string
+ */
+ public static function readContentsFrom( $file ) {
+
+ $file = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $file );
+
+ if ( !is_readable( $file ) ) {
+ throw new RuntimeException( "Could not open or read: $file" );
+ }
+
+ $contents = file_get_contents( $file );
+
+ // http://php.net/manual/en/function.file-get-contents.php
+ $contents = mb_convert_encoding(
+ $contents,
+ 'UTF-8',
+ mb_detect_encoding( $contents, 'UTF-8, ISO-8859-1, ISO-8859-2', true )
+ );
+
+ // https://stackoverflow.com/questions/2115549/php-difference-between-r-n-and-n
+ return str_replace( "\r\n", "\n", $contents );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/DummyFileCreator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/DummyFileCreator.php
new file mode 100644
index 00000000..102c44d6
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/DummyFileCreator.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace SMW\Tests\Utils\File;
+
+use RuntimeException;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class DummyFileCreator {
+
+ /**
+ * @var string
+ */
+ private $desiredDestName;
+
+ /**
+ * @var string
+ */
+ private $file = '';
+
+ /**
+ * @var integer
+ */
+ private $size = 100;
+
+ /**
+ * @since 2.1
+ *
+ * @param string $desiredDestName
+ *
+ * @return string
+ */
+ public function createEmptyFile( $desiredDestName ) {
+ $this->file = $this->createFile( $desiredDestName );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $desiredDestName
+ * @param string $contentCopyPath
+ *
+ * @return string
+ */
+ public function createFileWithCopyFrom( $desiredDestName, $contentCopyPath ) {
+ $this->file = $this->createFile( $desiredDestName, file_get_contents( $this->getFile( $contentCopyPath ) ) );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return string
+ */
+ public function getPath() {
+ return $this->file;
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function delete() {
+ unlink( $this->file );
+ }
+
+ private function createFile( $desiredDestName, $content = '' ) {
+
+ $filename = $this->getLocationForTemporaryFile( $desiredDestName );
+
+ $fh = fopen( $filename, 'w' );
+
+ if ( $content === '' ) {
+ ftruncate( $fh, $this->size );
+ } else {
+ fwrite( $fh, $content );
+ }
+
+ fclose( $fh );
+
+ return $this->getFile( $filename );
+ }
+
+ private function getLocationForTemporaryFile( $desiredDestName ) {
+ return sys_get_temp_dir() . '/' . $desiredDestName;
+ }
+
+ private function getFile( $path ) {
+
+ $path = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $path );
+
+ if ( is_readable( $path ) ) {
+ return $path;
+ }
+
+ throw new RuntimeException( "Expected an accessible {$path}" );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/JsonFileReader.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/JsonFileReader.php
new file mode 100644
index 00000000..dfe97b55
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/JsonFileReader.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace SMW\Tests\Utils\File;
+
+use RuntimeException;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class JsonFileReader {
+
+ /**
+ * @var string|null
+ */
+ private $file = null;
+
+ /**
+ * @var array|null
+ */
+ private $contents = null;
+
+ /**
+ * @since 2.1
+ *
+ * @param string|null $file
+ */
+ public function __construct( $file = null ) {
+ $this->setFile( $file );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $file
+ */
+ public function setFile( $file ) {
+ $this->file = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $file );
+ $this->contents = null;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return array
+ * @throws RuntimeException
+ */
+ public function read() {
+
+ if ( $this->contents === null && $this->isReadable() ) {
+ $this->contents = $this->decodeJsonFileContentsToArray( $this->file );
+ }
+
+ if ( $this->contents !== null ) {
+ return $this->contents;
+ }
+
+ throw new RuntimeException( "Expected a readable {$this->file} file" );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return boolean
+ */
+ public function isReadable() {
+ return is_file( $this->file ) && is_readable( $this->file );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return integer
+ * @throws RuntimeException
+ */
+ public function getModificationTime() {
+
+ if ( $this->isReadable() ) {
+ return filemtime( $this->file );
+ }
+
+ throw new RuntimeException( "Expected a readable {$this->file} file" );
+ }
+
+ private function decodeJsonFileContentsToArray( $file ) {
+
+ $json = file_get_contents( $file );
+
+ $json = preg_replace(
+ '~ ("(?:[^\\\"]+|\\\.)*") |' . // preserve strings
+ '/\* (?:[^*]+|\*+(?!/))* \*/ |' . // strip multi-line comments
+ '//\V* ~sx', // strip //-comments
+ '$1', $json );
+
+ $contents = json_decode( $json, true );
+
+ if ( $contents !== null && json_last_error() === JSON_ERROR_NONE ) {
+ return $contents;
+ }
+
+ throw new RuntimeException( $this->printDescriptiveJsonError( json_last_error() ) );
+ }
+
+ private function printDescriptiveJsonError( $errorCode ) {
+
+ $errorMessages = [
+ JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch, malformed JSON',
+ JSON_ERROR_CTRL_CHAR => 'Unexpected control character found, possibly incorrectly encoded',
+ JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
+ JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
+ JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded'
+ ];
+
+ return sprintf(
+ "Expected a JSON compatible format but failed with '%s'",
+ $errorMessages[$errorCode]
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/LocalFileUpload.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/LocalFileUpload.php
new file mode 100644
index 00000000..60ed77d8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/File/LocalFileUpload.php
@@ -0,0 +1,179 @@
+<?php
+
+namespace SMW\Tests\Utils\File;
+
+use RuntimeException;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use UploadBase;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class LocalFileUpload extends UploadBase {
+
+ /**
+ * @var boolean
+ */
+ private $removeTemporaryFile = true;
+
+ /**
+ * @var string
+ */
+ private $localUploadPath;
+
+ /**
+ * @var string
+ */
+ private $desiredDestName;
+
+ /**
+ * @var DummyFileCreator
+ */
+ private $dummyFileCreator;
+
+ /**
+ * @var string
+ */
+ private $error = '';
+
+ /**
+ * @since 2.1
+ *
+ * @param string $localUploadPath
+ * @param string $desiredDestName
+ */
+ public function __construct( $localUploadPath = '', $desiredDestName = '' ) {
+ $this->localUploadPath = $localUploadPath;
+ $this->desiredDestName = $desiredDestName;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param DummyFileCreator $dummyFileCreator
+ */
+ public function setDummyFileCreator( DummyFileCreator $dummyFileCreator ) {
+ $this->dummyFileCreator = $dummyFileCreator;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return string
+ */
+ public function getUploadError() {
+ return $this->error;
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function delete() {
+ unlink( $this->localUploadPath );
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $localUploadPath
+ * @param string $desiredDestName
+ * @param string $pageText
+ * @param string $comment
+ *
+ * @return boolean
+ */
+ public function doUploadCopyFromLocation( $localUploadPath, $desiredDestName, $pageText = '', $comment = '' ) {
+
+ if ( !$this->dummyFileCreator instanceof DummyFileCreator ) {
+ throw new RuntimeException( "Expected a DummyFileCreator instance." );
+ }
+
+ $this->dummyFileCreator->createFileWithCopyFrom(
+ $desiredDestName,
+ $localUploadPath
+ );
+
+ $this->doUploadFromLocation(
+ $this->dummyFileCreator->getPath(),
+ $desiredDestName,
+ $pageText,
+ $comment
+ );
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $localUploadPath
+ * @param string $desiredDestName
+ * @param string $pageText
+ * @param string $comment
+ *
+ * @return boolean
+ */
+ public function doUploadFromLocation( $localUploadPath, $desiredDestName, $pageText = '', $comment = '' ) {
+
+ $localUploadPath = $this->createReadablePath( $localUploadPath );
+
+ $this->initializePathInfo(
+ $desiredDestName,
+ $localUploadPath,
+ filesize( $localUploadPath ),
+ $this->removeTemporaryFile
+ );
+
+ $status = $this->performUpload(
+ $comment,
+ $pageText,
+ false,
+ new MockSuperUSer()
+ );
+
+ if ( !$status->isGood() ) {
+ $this->error = $status->getWikiText();
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $pageText
+ * @param string $comment
+ *
+ * @return boolean
+ */
+ public function doUpload( $pageText = '', $comment = '' ) {
+ return $this->doUploadFromLocation( $this->localUploadPath, $this->desiredDestName, $pageText, $comment );
+ }
+
+ /**
+ * @see UploadBase::initializeFromRequest
+ */
+ public function initializeFromRequest( &$request ) {
+ }
+
+ /**
+ * @see UploadBase::getSourceType
+ */
+ public function getSourceType() {
+ return 'file';
+ }
+
+ private function createReadablePath( $path ) {
+
+ $path = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $path );
+
+ if ( is_readable( $path ) ) {
+ return $path;
+ }
+
+ throw new RuntimeException( "Expected an accessible {$path}" );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/BerlinFactsheet.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/BerlinFactsheet.php
new file mode 100644
index 00000000..695cd0d0
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/BerlinFactsheet.php
@@ -0,0 +1,273 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Facts;
+
+use RuntimeException;
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\Subobject;
+use SMW\Tests\Utils\Fixtures\Properties\AreaProperty;
+use SMW\Tests\Utils\Fixtures\Properties\CityCategory;
+use SMW\Tests\Utils\Fixtures\Properties\FoundedProperty;
+use SMW\Tests\Utils\Fixtures\Properties\LocatedInProperty;
+use SMW\Tests\Utils\Fixtures\Properties\PopulationDensityProperty;
+use SMW\Tests\Utils\Fixtures\Properties\PopulationProperty;
+use SMW\Tests\Utils\Fixtures\Properties\TemperatureProperty;
+use SMW\Tests\Utils\Fixtures\Properties\YearProperty;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class BerlinFactsheet {
+
+ /**
+ * @var DIWikiPage
+ */
+ private $targetSubject = null;
+
+ /**
+ * @var DataValueFactory
+ */
+ private $dataValueFactory;
+
+ /**
+ * @since 2.1
+ *
+ * @param DIWikiPage|null $targetSubject
+ */
+ public function __construct( DIWikiPage $targetSubject = null ) {
+ $this->targetSubject = $targetSubject;
+
+ if ( $this->targetSubject === null ) {
+ $this->targetSubject = $this->asSubject();
+ }
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param DIWikiPage $targetSubject
+ */
+ public function setTargetSubject( DIWikiPage $targetSubject ) {
+ $this->targetSubject = $targetSubject;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIWikiPage
+ */
+ public function asSubject() {
+ return new DIWikiPage( 'Berlin', NS_MAIN );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function asEntity() {
+
+ $semanticData = new SemanticData( $this->asSubject() );
+ $semanticData->addDataValue( $this->getAreaValue() );
+ $semanticData->addDataValue( $this->getAverageHighTemperatureValue() );
+ $semanticData->addDataValue( $this->getPopulationValue() );
+ $semanticData->addDataValue( $this->getPopulationDensityValue() );
+ $semanticData->addDataValue( $this->getLocatedInValue() );
+ $semanticData->addDataValue( $this->getFoundedValue() );
+ $semanticData->addSubobject( $this->getDemographics() );
+
+ $cityCategory = new CityCategory();
+
+ $semanticData->addDataValue( $cityCategory->getCategoryValue() );
+
+ return $semanticData;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DataValue
+ */
+ public function getLocatedInValue() {
+
+ $locatedInProperty = new LocatedInProperty();
+
+ return $this->dataValueFactory->newDataValueByItem(
+ new DIWikiPage( 'Germany', NS_MAIN ),
+ $locatedInProperty->getProperty()
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Berlin
+ *
+ * @return DataValue
+ */
+ public function getAreaValue() {
+
+ $areaProperty = new AreaProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $areaProperty->getProperty(),
+ '891.85 km²'
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Berlin
+ *
+ * @return DataValue
+ */
+ public function getFoundedValue() {
+
+ $foundedProperty = new FoundedProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $foundedProperty->getProperty(),
+ '1237'
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Berlin
+ *
+ * @return DataValue
+ */
+ public function getAverageHighTemperatureValue() {
+
+ $temperatureProperty = new TemperatureProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $temperatureProperty->getProperty(),
+ '13.4 °C',
+ 'Average high temperature'
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Berlin
+ *
+ * @return DataValue
+ */
+ public function getPopulationValue() {
+
+ $populationProperty = new PopulationProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $populationProperty->getProperty(),
+ '3517424'
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Demographics_of_Berlin
+ *
+ * @return DataValue
+ */
+ public function getPopulationDensityValue() {
+
+ if ( $this->targetSubject === null ) {
+ throw new RuntimeException( 'Expected a target subject' );
+ }
+
+ $populationDensityProperty = new PopulationDensityProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $populationDensityProperty->getProperty(),
+ '3900;1 km²',
+ 'Population density',
+ $this->targetSubject
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Demographics_of_Berlin
+ *
+ * @return Subobject
+ */
+ public function getDemographics() {
+
+ if ( $this->targetSubject === null ) {
+ throw new RuntimeException( 'Expected a target subject' );
+ }
+
+ $subobject = new Subobject( $this->targetSubject->getTitle() );
+ $subobject->setEmptyContainerForId( 'Berlin#Demographics' );
+
+ $yearProperty = new YearProperty();
+
+ $yearDataValue = $this->dataValueFactory->newDataValueByProperty(
+ $yearProperty->getProperty(),
+ '2013'
+ );
+
+ $subobject->addDataValue( $yearDataValue );
+ $subobject->addDataValue( $this->getAreaValue() );
+ $subobject->addDataValue( $this->getPopulationValue() );
+ $subobject->addDataValue( $this->getPopulationDensityValue() );
+
+ return $subobject;
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function purge() {
+
+ $subjects = [];
+
+ $subjects[] = $this->asSubject();
+ $subjects[] = $this->targetSubject;
+ $subjects[] = $this->getFoundedValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getAreaValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getAverageHighTemperatureValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getPopulationValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getPopulationDensityValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getDemographics()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getLocatedInValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getLocatedInValue()->getDataItem();
+
+ // Record type needs extra attention
+ $dataItems = $this->getPopulationDensityValue()->getDataItems();
+
+ foreach ( $dataItems as $dataItem ) {
+ $subjects[] = $dataItem;
+ }
+
+ // Clean-up subobject
+ $properties = $this->getDemographics()->getSemanticData()->getProperties();
+
+ foreach ( $properties as $property ) {
+ $subjects[] = $property->getDiWikiPage();
+ }
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+
+ foreach ( $subjects as $subject ) {
+ if ( $subject instanceof DIWikiPage ) {
+ $pageDeleter->deletePage( $subject->getTitle() );
+ }
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/FranceFactsheet.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/FranceFactsheet.php
new file mode 100644
index 00000000..f864442c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/FranceFactsheet.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Facts;
+
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\Tests\Utils\Fixtures\Properties\CountryCategory;
+use SMW\Tests\Utils\Fixtures\Properties\LocatedInProperty;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class FranceFactsheet {
+
+ /**
+ * @var DIWikiPage
+ */
+ private $targetSubject = null;
+
+ /**
+ * @var DataValueFactory
+ */
+ private $dataValueFactory;
+
+ /**
+ * @since 2.1
+ *
+ * @param DIWikiPage|null $targetSubject
+ */
+ public function __construct( DIWikiPage $targetSubject = null ) {
+ $this->targetSubject = $targetSubject;
+
+ if ( $this->targetSubject === null ) {
+ $this->targetSubject = $this->asSubject();
+ }
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param DIWikiPage $targetSubject
+ */
+ public function setTargetSubject( DIWikiPage $targetSubject ) {
+ $this->targetSubject = $targetSubject;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIWikiPage
+ */
+ public function asSubject() {
+ return new DIWikiPage( 'France', NS_MAIN );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function asEntity() {
+
+ $semanticData = new SemanticData( $this->asSubject() );
+ $semanticData->addDataValue( $this->getLocatedInValue() );
+
+ $countryCategory = new CountryCategory();
+
+ $semanticData->addDataValue( $countryCategory->getCategoryValue() );
+
+ return $semanticData;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DataValue
+ */
+ public function getLocatedInValue() {
+
+ $locatedInProperty = new LocatedInProperty();
+
+ return $this->dataValueFactory->newDataValueByItem(
+ DIWikiPage::newFromText( 'European Union', NS_MAIN ),
+ $locatedInProperty->getProperty(),
+ 'EU'
+ );
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function purge() {
+
+ $subjects = [];
+
+ $subjects[] = $this->asSubject();
+ $subjects[] = $this->targetSubject;
+ $subjects[] = $this->getLocatedInValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getLocatedInValue()->getDataItem();
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+
+ foreach ( $subjects as $subject ) {
+ if ( $subject instanceof DIWikiPage ) {
+ $pageDeleter->deletePage( $subject->getTitle() );
+ }
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/ParisFactsheet.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/ParisFactsheet.php
new file mode 100644
index 00000000..d8ad459c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Facts/ParisFactsheet.php
@@ -0,0 +1,254 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Facts;
+
+use RuntimeException;
+use SMW\DataValueFactory;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\Subobject;
+use SMW\Tests\Utils\Fixtures\Properties\AreaProperty;
+use SMW\Tests\Utils\Fixtures\Properties\CityCategory;
+use SMW\Tests\Utils\Fixtures\Properties\LocatedInProperty;
+use SMW\Tests\Utils\Fixtures\Properties\PopulationDensityProperty;
+use SMW\Tests\Utils\Fixtures\Properties\PopulationProperty;
+use SMW\Tests\Utils\Fixtures\Properties\TemperatureProperty;
+use SMW\Tests\Utils\Fixtures\Properties\YearProperty;
+use SMW\Tests\Utils\UtilityFactory;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ParisFactsheet {
+
+ /**
+ * @var DIWikiPage
+ */
+ private $targetSubject = null;
+
+ /**
+ * @var DataValueFactory
+ */
+ private $dataValueFactory;
+
+ /**
+ * @since 2.1
+ *
+ * @param DIWikiPage|null $targetSubject
+ */
+ public function __construct( DIWikiPage $targetSubject = null ) {
+ $this->targetSubject = $targetSubject;
+
+ if ( $this->targetSubject === null ) {
+ $this->targetSubject = $this->asSubject();
+ }
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param DIWikiPage $targetSubject
+ */
+ public function setTargetSubject( DIWikiPage $targetSubject ) {
+ $this->targetSubject = $targetSubject;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIWikiPage
+ */
+ public function asSubject() {
+ return new DIWikiPage( 'Paris', NS_MAIN );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function asEntity() {
+
+ $semanticData = new SemanticData( $this->asSubject() );
+ $semanticData->addDataValue( $this->getAreaValue() );
+ $semanticData->addDataValue( $this->getAverageHighTemperatureValue() );
+ $semanticData->addDataValue( $this->getPopulationValue() );
+ $semanticData->addDataValue( $this->getPopulationDensityValue() );
+ $semanticData->addDataValue( $this->getLocatedInValue() );
+ $semanticData->addSubobject( $this->getDemographics() );
+
+ $cityCategory = new CityCategory();
+
+ $semanticData->addDataValue( $cityCategory->getCategoryValue() );
+
+ return $semanticData;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DataValue
+ */
+ public function getLocatedInValue() {
+
+ $locatedInProperty = new LocatedInProperty();
+
+ return $this->dataValueFactory->newDataValueByItem(
+ new DIWikiPage( 'France', NS_MAIN ),
+ $locatedInProperty->getProperty()
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Berlin
+ *
+ * @return DataValue
+ */
+ public function getAreaValue() {
+
+ $areaProperty = new AreaProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $areaProperty->getProperty(),
+ '105.40 km²',
+ 'City of Paris'
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Berlin
+ *
+ * @return DataValue
+ */
+ public function getAverageHighTemperatureValue() {
+
+ $temperatureProperty = new TemperatureProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $temperatureProperty->getProperty(),
+ '16.0 °C',
+ 'Average high temperature'
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Demographics_of_Paris
+ *
+ * @return DataValue
+ */
+ public function getPopulationValue() {
+
+ $populationProperty = new PopulationProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $populationProperty->getProperty(),
+ '2234105'
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Demographics_of_Paris
+ *
+ * @return DataValue
+ */
+ public function getPopulationDensityValue() {
+
+ if ( $this->targetSubject === null ) {
+ throw new RuntimeException( 'Expected a target subject' );
+ }
+
+ $populationDensityProperty = new PopulationDensityProperty();
+
+ return $this->dataValueFactory->newDataValueByProperty(
+ $populationDensityProperty->getProperty(),
+ '20169;1 km²',
+ 'Population density',
+ $this->targetSubject
+ );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @see https://en.wikipedia.org/wiki/Demographics_of_Paris
+ *
+ * @return Subobject
+ */
+ public function getDemographics() {
+
+ if ( $this->targetSubject === null ) {
+ throw new RuntimeException( 'Expected a target subject' );
+ }
+
+ $subobject = new Subobject( $this->targetSubject->getTitle() );
+ $subobject->setEmptyContainerForId( 'Paris#Demographics' );
+
+ $yearProperty = new YearProperty();
+
+ $yearDataValue = $this->dataValueFactory->newDataValueByProperty(
+ $yearProperty->getProperty(),
+ '2009'
+ );
+
+ $subobject->addDataValue( $yearDataValue );
+ $subobject->addDataValue( $this->getAreaValue() );
+ $subobject->addDataValue( $this->getPopulationValue() );
+ $subobject->addDataValue( $this->getPopulationDensityValue() );
+
+ return $subobject;
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function purge() {
+
+ $subjects = [];
+
+ $subjects[] = $this->asSubject();
+ $subjects[] = $this->targetSubject;
+ $subjects[] = $this->getAreaValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getAverageHighTemperatureValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getPopulationValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getPopulationDensityValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getDemographics()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getLocatedInValue()->getProperty()->getDiWikiPage();
+ $subjects[] = $this->getLocatedInValue()->getDataItem();
+
+ // Record type needs extra attention
+ $dataItems = $this->getPopulationDensityValue()->getDataItems();
+
+ foreach ( $dataItems as $dataItem ) {
+ $subjects[] = $dataItem;
+ }
+
+ // Clean-up subobject
+ $properties = $this->getDemographics()->getSemanticData()->getProperties();
+
+ foreach ( $properties as $property ) {
+ $subjects[] = $property->getDiWikiPage();
+ }
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+
+ foreach ( $subjects as $subject ) {
+ if ( $subject instanceof DIWikiPage ) {
+ $pageDeleter->deletePage( $subject->getTitle() );
+ }
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.json b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.json
new file mode 100644
index 00000000..bf85abf4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.json
@@ -0,0 +1,13 @@
+{
+ "text": "Lorem ipsum dolor sit amet consectetuer eu vitae consectetuer ac accumsan.",
+ "keywords": [
+ "Tellus Aenean",
+ "Mauris Aenean neque augue"
+ ],
+ "content": [
+ {
+ "name": "convallis interdum a nibh laoreet",
+ "url": "http://example.org"
+ }
+ ]
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.txt b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.txt
new file mode 100644
index 00000000..69ce20a4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/File/LoremIpsum.txt
@@ -0,0 +1,3 @@
+Lorem ipsum dolor sit amet consectetuer eu vitae consectetuer ac accumsan. Tellus Aenean porta odio volutpat vel cursus et wisi eu ac. Id Curabitur nec congue dolor magna Pellentesque Suspendisse et est Nulla. Pharetra neque Nullam ornare mauris feugiat ultrices pellentesque dui pretium libero. Tellus Curabitur Lorem et enim id.
+
+Justo id convallis interdum a nibh laoreet Mauris Aenean neque augue. Pretium non eget Phasellus malesuada justo ut gravida Maecenas orci ante. Vestibulum sociis Lorem Nulla Phasellus at Nam adipiscing ac Sed ut. Mauris rhoncus ut faucibus tempus laoreet lorem morbi eu nascetur fermentum. Consectetuer congue ut aliquam leo nibh eget auctor nibh ullamcorper nonummy. Ac nibh.
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesCleaner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesCleaner.php
new file mode 100644
index 00000000..617ef0e3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesCleaner.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures;
+
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class FixturesCleaner {
+
+ /**
+ * @since 2.1
+ *
+ * @param array $subjects
+ *
+ * @return FixturesCleaner
+ */
+ public function purgeSubjects( array $subjects ) {
+
+ $pageDeleter = UtilityFactory::getInstance()->newPageDeleter();
+ $pageDeleter->doDeletePoolOfPages( $subjects );
+
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return FixturesCleaner
+ */
+ public function purgeAllKnownFacts() {
+ $fixturesProvider = new FixturesProvider();
+ return $this->purgeFacts( $fixturesProvider->getListOfFactsheetInstances() );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param array $facts
+ *
+ * @return FixturesCleaner
+ */
+ public function purgeFacts( array $facts ) {
+
+ foreach ( $facts as $fact ) {
+ $fact->purge();
+ }
+
+ return $this;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFactory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFactory.php
new file mode 100644
index 00000000..40edd221
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFactory.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class FixturesFactory {
+
+ /**
+ * @since 2.1
+ *
+ * @return FixturesProvider
+ */
+ public function newFixturesProvider() {
+ return new FixturesProvider();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return FixturesCleaner
+ */
+ public function newFixturesCleaner() {
+ return new FixturesCleaner();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return FixturesFileProvider
+ */
+ public function newFixturesFileProvider() {
+ return new FixturesFileProvider();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFileProvider.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFileProvider.php
new file mode 100644
index 00000000..71ba744a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesFileProvider.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures;
+
+use SMW\Tests\Utils\File\DummyFileCreator;
+use SMW\Tests\Utils\File\LocalFileUpload;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class FixturesFileProvider {
+
+ /**
+ * @since 2.1
+ *
+ * @param string $desiredDestName
+ *
+ * @return DummyFileCreator
+ */
+ public function newDummyJsonFile( $desiredDestName ) {
+
+ $dummyFileCreator = new DummyFileCreator();
+ $dummyFileCreator->createFileWithCopyFrom( $desiredDestName, __DIR__ . '/File/' . 'LoremIpsum.json' );
+
+ return $dummyFileCreator;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $desiredDestName
+ *
+ * @return DummyFileCreator
+ */
+ public function newDummyTextFile( $desiredDestName ) {
+
+ $dummyFileCreator = new DummyFileCreator();
+ $dummyFileCreator->createFileWithCopyFrom( $desiredDestName, __DIR__ . '/File/' . 'LoremIpsum.txt' );
+
+ return $dummyFileCreator;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $desiredDestName
+ *
+ * @return LocalFileUpload
+ */
+ public function newUploadForDummyTextFile( $desiredDestName ) {
+
+ $dummyTextFile = $this->newDummyTextFile( $desiredDestName );
+
+ return new LocalFileUpload(
+ $dummyTextFile->getPath(),
+ $desiredDestName
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesProvider.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesProvider.php
new file mode 100644
index 00000000..b3f3893e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/FixturesProvider.php
@@ -0,0 +1,165 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures;
+
+use RuntimeException;
+use SMW\Store;
+use SMW\Tests\Utils\Fixtures\Facts\BerlinFactsheet;
+use SMW\Tests\Utils\Fixtures\Facts\FranceFactsheet;
+use SMW\Tests\Utils\Fixtures\Facts\ParisFactsheet;
+use SMW\Tests\Utils\Fixtures\Properties\AreaProperty;
+use SMW\Tests\Utils\Fixtures\Properties\BookRecordProperty;
+use SMW\Tests\Utils\Fixtures\Properties\CityCategory;
+use SMW\Tests\Utils\Fixtures\Properties\FoundedProperty;
+use SMW\Tests\Utils\Fixtures\Properties\LocatedInProperty;
+use SMW\Tests\Utils\Fixtures\Properties\PopulationDensityProperty;
+use SMW\Tests\Utils\Fixtures\Properties\PopulationProperty;
+use SMW\Tests\Utils\Fixtures\Properties\StatusProperty;
+use SMW\Tests\Utils\Fixtures\Properties\TitleProperty;
+use SMW\Tests\Utils\Fixtures\Properties\UrlProperty;
+use SMW\Tests\Utils\Fixtures\Properties\YearProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class FixturesProvider {
+
+ private $factsheets = null;
+ private $properties = null;
+ private $categories = null;
+
+ /**
+ * @since 2.1
+ */
+ public function setupDependencies( Store $store ) {
+
+ // This needs to happen before access to a property object is granted
+
+ // $pageCreator = UtilityFactory::getInstance()->newPageCreator();
+
+ foreach ( $this->getListOfPropertyInstances() as $propertyInstance ) {
+ $store->updateData( $propertyInstance->getDependencies() );
+ }
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return array
+ */
+ public function getListOfFactsheetInstances() {
+ return [
+ 'berlin' => new BerlinFactsheet(),
+ 'paris' => new ParisFactsheet(),
+ 'france' => new FranceFactsheet()
+ ];
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return array
+ */
+ public function getListOfPropertyInstances() {
+ return [
+ 'area' => new AreaProperty(),
+ 'populationdensity' => new PopulationDensityProperty(),
+ // 'capitalof' => new CapitalOfProperty(),
+ 'status' => new StatusProperty(),
+ 'population' => new PopulationProperty(),
+ 'founded' => new FoundedProperty(),
+ 'locatedin' => new LocatedInProperty(),
+ 'bookrecord' => new BookRecordProperty(),
+ 'year' => new YearProperty(),
+ 'title' => new TitleProperty(),
+ 'url' => new UrlProperty()
+ ];
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return array
+ */
+ public function getListOfCategoryInstances() {
+ return [
+ 'city' => new CityCategory()
+ ];
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIProperty
+ * @throws RuntimeException
+ */
+ public function getProperty( $id ) {
+
+ $id = strtolower( $id );
+
+ if ( $this->properties === null ) {
+ $this->properties = $this->getListOfPropertyInstances();
+ };
+
+ if ( isset( $this->properties[$id] ) ) {
+ return $this->properties[$id]->getProperty();
+ }
+
+ throw new RuntimeException( "$id is an unknown requested property" );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIProperty
+ * @throws RuntimeException
+ */
+ public function getCategory( $id ) {
+
+ $id = strtolower( $id );
+
+ if ( $this->categories === null ) {
+ $this->categories = $this->getListOfCategoryInstances();
+ };
+
+ if ( isset( $this->categories[$id] ) ) {
+ return $this->categories[$id];
+ }
+
+ throw new RuntimeException( "$id is an unknown requested property" );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return Factsheet
+ * @throws RuntimeException
+ */
+ public function getFactsheet( $id ) {
+
+ $id = strtolower( $id );
+
+ if ( $this->factsheets === null ) {
+ $this->factsheets = $this->getListOfFactsheetInstances();
+ };
+
+ if ( isset( $this->factsheets[$id] ) ) {
+ return $this->factsheets[$id];
+ }
+
+ throw new RuntimeException( "$id is an unknown requested fact" );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return FixturesCleaner
+ */
+ public function getCleaner() {
+ return new FixturesCleaner();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/InvalidCustomRespositoryConnector.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/InvalidCustomRespositoryConnector.php
new file mode 100644
index 00000000..194f6889
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/InvalidCustomRespositoryConnector.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class InvalidCustomRespositoryConnector {
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/AreaProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/AreaProperty.php
new file mode 100644
index 00000000..f200f19b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/AreaProperty.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\SemanticData;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class AreaProperty extends FixtureProperty {
+
+ /**
+ * @var array
+ */
+ private $conversionValues = [
+ '1 km²',
+ '0.38610 sq mi',
+ '1000 m²',
+ '247.1054 acre',
+ '988.4215 rood'
+ ];
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( 'Area' );
+ $this->property->setPropertyTypeId( '_qty' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function getDependencies() {
+
+ $semanticData = parent::getDependencies();
+
+ $dataValueFactory = DataValueFactory::getInstance();
+
+ foreach( $this->conversionValues as $conversionValue ) {
+ $semanticData->addDataValue(
+ $dataValueFactory->newDataValueByProperty(
+ new DIProperty( '_CONV' ),
+ $conversionValue
+ )
+ );
+ }
+
+ return $semanticData;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/BookRecordProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/BookRecordProperty.php
new file mode 100644
index 00000000..ecc13f11
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/BookRecordProperty.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+use SMW\SemanticData;
+use SMWDIBlob as DIBlob;
+
+/**
+ * Simplified book record
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class BookRecordProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Book record' );
+ $this->property->setPropertyTypeId( '_rec' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function getDependencies() {
+
+ $semanticData = parent::getDependencies();
+
+ $titleProperty = new TitleProperty();
+ $yearProperty = new YearProperty();
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_LIST' ),
+ new DIBlob(
+ $titleProperty->getProperty()->getKey() . ';' .
+ $yearProperty->getProperty()->getKey()
+ )
+ );
+
+ return $semanticData;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CapitalOfProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CapitalOfProperty.php
new file mode 100644
index 00000000..57f338df
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CapitalOfProperty.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+use SMW\SemanticData;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class CapitalOfProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Capital of' );
+ $this->property->setPropertyTypeId( '_wpg' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function getDependencies() {
+
+ $semanticData = parent::getDependencies();
+
+ $locatedInProperty = new LocatedInProperty();
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_SUBP' ),
+ $locatedInProperty->getProperty()->getDiWikiPage()
+ );
+
+ return $semanticData;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CityCategory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CityCategory.php
new file mode 100644
index 00000000..eb27d661
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CityCategory.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWiKiPage;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class CityCategory extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( '_INST' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIWiKiPage
+ */
+ public function asSubject() {
+ return new DIWiKiPage( 'City', NS_CATEGORY );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DataValue
+ */
+ public function getCategoryValue() {
+ return DataValueFactory::getInstance()->newDataValueByItem(
+ $this->asSubject(),
+ $this->getProperty()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CoordinatesProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CoordinatesProperty.php
new file mode 100644
index 00000000..0554b8d4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CoordinatesProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class CoordinatesProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( 'Coordinates' );
+ $this->property->setPropertyTypeId( '_geo' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CountryCategory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CountryCategory.php
new file mode 100644
index 00000000..2f821be8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/CountryCategory.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWiKiPage;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class CountryCategory {
+
+ /**
+ * @var DIProperty
+ */
+ private $property = null;
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( '_INST' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIProperty
+ */
+ public function getProperty() {
+ return $this->property;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DIWiKiPage
+ */
+ public function asSubject() {
+ return new DIWiKiPage( 'Country', NS_CATEGORY );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return DataValue
+ */
+ public function getCategoryValue() {
+ return DataValueFactory::getInstance()->newDataValueByItem(
+ $this->asSubject(),
+ $this->getProperty()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/DescriptionProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/DescriptionProperty.php
new file mode 100644
index 00000000..1e743b90
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/DescriptionProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class DescriptionProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( 'Description' );
+ $this->property->setPropertyTypeId( '_txt' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/EmailProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/EmailProperty.php
new file mode 100644
index 00000000..0f8c7bec
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/EmailProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class EmailProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Email' );
+ $this->property->setPropertyTypeId( '_ema' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FixtureProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FixtureProperty.php
new file mode 100644
index 00000000..430a6841
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FixtureProperty.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\SemanticData;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+abstract class FixtureProperty {
+
+ /**
+ * @var DIProperty
+ */
+ protected $property = null;
+
+ /**
+ * @since 2.1
+ *
+ * @return DIProperty
+ */
+ public function getProperty() {
+ return $this->property;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function getDependencies() {
+
+ $semanticData = new SemanticData( $this->property->getDiWikiPage() );
+
+ $semanticData->addDataValue(
+ DataValueFactory::getInstance()->newDataValueByProperty(
+ new DIProperty( '_TYPE' ),
+ $this->property->findPropertyTypeID()
+ )
+ );
+
+ return $semanticData;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FoundedProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FoundedProperty.php
new file mode 100644
index 00000000..86bbf0ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/FoundedProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class FoundedProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( 'Founded' );
+ $this->property->setPropertyTypeId( '_dat' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/LocatedInProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/LocatedInProperty.php
new file mode 100644
index 00000000..23ae40bf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/LocatedInProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class LocatedInProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Located in' );
+ $this->property->setPropertyTypeId( '_wpg' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationDensityProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationDensityProperty.php
new file mode 100644
index 00000000..b9e65009
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationDensityProperty.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+use SMW\SemanticData;
+use SMWDIBlob as DIBlob;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PopulationDensityProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Population density' );
+ $this->property->setPropertyTypeId( '_rec' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function getDependencies() {
+
+ $semanticData = parent::getDependencies();
+
+ $populationProperty = new PopulationProperty();
+ $areaProperty = new AreaProperty();
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_LIST' ),
+ new DIBlob(
+ $populationProperty->getProperty()->getKey() . ';' .
+ $areaProperty->getProperty()->getKey()
+ )
+ );
+
+ return $semanticData;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationProperty.php
new file mode 100644
index 00000000..a60315e2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/PopulationProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PopulationProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( 'Population' );
+ $this->property->setPropertyTypeId( '_num' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/StatusProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/StatusProperty.php
new file mode 100644
index 00000000..5fd13f53
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/StatusProperty.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+use SMW\SemanticData;
+use SMWDIBlob as DIBlob;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class StatusProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Status' );
+ $this->property->setPropertyTypeId( '_txt' );
+ }
+
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticData
+ */
+ public function getDependencies() {
+
+ $semanticData = parent::getDependencies();
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_PVAL' ),
+ new DIBlob( 'open' )
+ );
+
+ $semanticData->addPropertyObjectValue(
+ new DIProperty( '_PVAL' ),
+ new DIBlob( 'closed' )
+ );
+
+ return $semanticData;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TelephoneNumberProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TelephoneNumberProperty.php
new file mode 100644
index 00000000..20fbf125
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TelephoneNumberProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class TelephoneNumberProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Telephone number' );
+ $this->property->setPropertyTypeId( '_tel' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TemperatureProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TemperatureProperty.php
new file mode 100644
index 00000000..1dfcf818
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TemperatureProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class TemperatureProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( 'Temperature' );
+ $this->property->setPropertyTypeId( '_tem' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TitleProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TitleProperty.php
new file mode 100644
index 00000000..0e598a3a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/TitleProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class TitleProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Title' );
+ $this->property->setPropertyTypeId( '_wpg' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/UrlProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/UrlProperty.php
new file mode 100644
index 00000000..58e1fc12
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/UrlProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class UrlProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = DIProperty::newFromUserLabel( 'Url' );
+ $this->property->setPropertyTypeId( '_uri' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/YearProperty.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/YearProperty.php
new file mode 100644
index 00000000..b5afd2bb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Properties/YearProperty.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Properties;
+
+use SMW\DIProperty;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class YearProperty extends FixtureProperty {
+
+ /**
+ * @since 2.1
+ */
+ public function __construct() {
+ $this->property = new DIProperty( 'Year' );
+ $this->property->setPropertyTypeId( '_dat' );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/FakeRawResultProvider.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/FakeRawResultProvider.php
new file mode 100644
index 00000000..ed67f98e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/FakeRawResultProvider.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\Utils\Fixtures\Results;
+
+use RuntimeException;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group semantic-mediawiki-sparql
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class FakeRawResultProvider {
+
+ /**
+ * @see https://www.w3.org/TR/rdf-sparql-query/#ask
+ */
+ public function getEmptySparqlResultXml() {
+ return $this->getFixtureContentsFor( 'empty-sparql-result.xml' );
+ }
+
+ /**
+ * @see http://www.w3.org/2009/sparql/xml-results/output2.srx
+ */
+ public function getBooleanSparqlResultXml() {
+ return $this->getFixtureContentsFor( 'boolean-sparql-result.xml' );
+ }
+
+ public function getStringTypeLiteralSparqlResultXml() {
+ return $this->getFixtureContentsFor( 'string-type-literal-sparql-result.xml' );
+ }
+
+ public function getUriResourceSparqlResultXml() {
+ return $this->getFixtureContentsFor( 'uri-resource-sparql-result.xml' );
+ }
+
+ public function getNonTypeLiteralResultXml() {
+ return $this->getFixtureContentsFor( 'nontype-literal-sparql-result.xml' );
+ }
+
+ public function getIntegerTypeLiteralSparqlResultXml() {
+ return $this->getFixtureContentsFor( 'integer-type-literal-sparql-result.xml' );
+ }
+
+ public function getMixedRowsSparqlResultXml() {
+ return $this->getFixtureContentsFor( 'mixed-rows-sparql-result.xml' );
+ }
+
+ public function getInvalidSparqlResultXml() {
+ return $this->getFixtureContentsFor( 'invalid-sparql-result.xml' );
+ }
+
+ public function getMixedRowsSparqlResultUtf8Xml() {
+ return $this->getFixtureContentsFor( 'mixed-rows-sparql-result-utf8.xml' );
+ }
+
+ private function getFixtureContentsFor( $fixture ) {
+ if ( $file = $this->isReadableFile( $this->getFixtureLocation() . $fixture ) ) {
+ return file_get_contents( $file );
+ }
+ }
+
+ private function getFixtureLocation() {
+ return __DIR__ . '/' . 'XML' . '/';
+ }
+
+ private function isReadableFile( $file ) {
+
+ if ( is_readable( $file ) ) {
+ return $file;
+ }
+
+ throw new RuntimeException( "{$file} is not accessible" );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/boolean-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/boolean-sparql-result.xml
new file mode 100644
index 00000000..99a2c61a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/boolean-sparql-result.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ </head>
+ <boolean>true</boolean>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/empty-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/empty-sparql-result.xml
new file mode 100644
index 00000000..4157ec87
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/empty-sparql-result.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="s"/>
+ <variable name="r"/>
+ </head>
+ <results>
+ </results>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/integer-type-literal-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/integer-type-literal-sparql-result.xml
new file mode 100644
index 00000000..1dc3152e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/integer-type-literal-sparql-result.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="count"/>
+ </head>
+ <results>
+ <result>
+ <binding name="count"><literal datatype="http://www.w3.org/2001/XMLSchema#integer">1</literal></binding>
+ </result>
+ </results>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/invalid-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/invalid-sparql-result.xml
new file mode 100644
index 00000000..4baedb6a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/invalid-sparql-result.xml
@@ -0,0 +1,8 @@
+
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ </head>
+ <results>
+ </results>
+</sparql>
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result-utf8.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result-utf8.xml
new file mode 100644
index 00000000..dc84a425
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result-utf8.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="result"/>
+ </head>
+ <results>
+ <result>
+ <binding name="result"><uri>http://example.org/id/F安o</uri></binding>
+ </result>
+ <result>
+ <binding name="result"><uri>http://example.org/id/B定ar</uri></binding>
+ </result>
+ <result>
+ <binding name="result"><literal datatype="http://www.w3.org/2001/XMLSchema#string">Quux安定</literal></binding>
+ </result>
+ </results>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result.xml
new file mode 100644
index 00000000..e59eabf2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/mixed-rows-sparql-result.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="result"/>
+ </head>
+ <results>
+ <result>
+ <binding name="result"><uri>http://example.org/id/Foo</uri></binding>
+ </result>
+ <result>
+ <binding name="result"><uri>http://example.org/id/Bar</uri></binding>
+ </result>
+ <result>
+ <binding name="result"><literal datatype="http://www.w3.org/2001/XMLSchema#string">Quux</literal></binding>
+ </result>
+ </results>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/nontype-literal-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/nontype-literal-sparql-result.xml
new file mode 100644
index 00000000..65fd4073
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/nontype-literal-sparql-result.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="s"/>
+ <variable name="r"/>
+ </head>
+ <results>
+ <result>
+ <binding name="s"><literal>Has foo</literal></binding>
+ </result>
+ </results>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/string-type-literal-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/string-type-literal-sparql-result.xml
new file mode 100644
index 00000000..cfb5a542
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/string-type-literal-sparql-result.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="result"/>
+ </head>
+ <results>
+ <result>
+ <binding name="result"><literal datatype="http://www.w3.org/2001/XMLSchema#string">Foo</literal></binding>
+ </result>
+ </results>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/uri-resource-sparql-result.xml b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/uri-resource-sparql-result.xml
new file mode 100644
index 00000000..bd918ee7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Fixtures/Results/XML/uri-resource-sparql-result.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<sparql xmlns="http://www.w3.org/2005/sparql-results#">
+ <head>
+ <variable name="result"/>
+ </head>
+ <results>
+ <result>
+ <binding name="result"><uri>http://example.org/id/Foo</uri></binding>
+ </result>
+ </results>
+</sparql> \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/GlobalsProvider.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/GlobalsProvider.php
new file mode 100644
index 00000000..ad1412bb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/GlobalsProvider.php
@@ -0,0 +1,90 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use InvalidArgumentException;
+
+/**
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class GlobalsProvider {
+
+ /**
+ * @var GlobalsProvider
+ */
+ private static $instance = null;
+
+ /**
+ * @var array
+ */
+ private $container = null;
+
+ /**
+ * @since 1.9.1
+ *
+ * @return GlobalsProvider
+ */
+ public static function getInstance() {
+
+ if ( self::$instance === null ) {
+ self::$instance = new self();
+ }
+
+ return self::$instance->setContainer( $GLOBALS );
+ }
+
+ /**
+ * @since 1.9.1
+ */
+ public static function clear() {
+ self::$instance = null;
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param string $key
+ *
+ * @return mixed
+ */
+ public function get( $key ) {
+
+ if ( is_string( $key ) && $this->contains( $key ) ) {
+ return $this->lookup( $key );
+ }
+
+ throw new InvalidArgumentException( 'Configuration key is unkown' );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function set( $key, $value ) {
+
+ if ( is_string( $key ) ) {
+ $this->container[$key] = $value;
+ }
+
+ return $this;
+ }
+
+ protected function setContainer( $container ) {
+ $this->container = $container;
+ return $this;
+ }
+
+ protected function contains( $key ) {
+ return isset( $this->container[$key] ) || array_key_exists( $key, $this->container );
+ }
+
+ protected function lookup( $key ) {
+ return $this->container[$key];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/InSemanticDataFetcher.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/InSemanticDataFetcher.php
new file mode 100644
index 00000000..ccb50f8c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/InSemanticDataFetcher.php
@@ -0,0 +1,61 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use SMW\Store;
+use SMWRequestOptions as RequestOptions;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class InSemanticDataFetcher {
+
+ /**
+ * @var Store
+ */
+ private $store = null;
+
+ /**
+ * @since 2.0
+ *
+ * @param Store $store
+ */
+ public function __construct( Store $store ) {
+ $this->store = $store;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return SemanticData
+ */
+ public function getSemanticData( DIWikiPage $subject ) {
+
+ $requestOptions = new RequestOptions();
+ $requestOptions->sort = true;
+
+ $semanticData = new SemanticData( $subject );
+
+ $incomingProperties = $this->store->getInProperties( $subject, $requestOptions );
+
+ foreach ( $incomingProperties as $property ) {
+ $values = $this->store->getPropertySubjects( $property, null );
+
+ foreach ( $values as $value ) {
+ $semanticData->addPropertyObjectValue( $property, $value );
+ }
+ }
+
+ return $semanticData;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/CoreMockObjectRepository.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/CoreMockObjectRepository.php
new file mode 100644
index 00000000..65c502e8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/CoreMockObjectRepository.php
@@ -0,0 +1,661 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+use DataValues\DataValue;
+use OutOfBoundsException;
+use SMW\ContentParser;
+use SMW\DependencyContainer;
+use SMW\DependencyObject;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Factbox\Factbox;
+use SMW\MediaWiki\PageInfoProvider;
+use SMW\ParserData;
+use SMW\Query\Language\Description;
+use SMW\Query\PrintRequest;
+use SMW\SemanticData;
+use SMW\SQLStore\TableDefinition;
+use SMW\Store;
+use SMW\Store\CacheableResultCollector;
+use SMWDataItem;
+use SMWDIError;
+use SMWQuery;
+use SMWQueryResult;
+use SMWResultArray;
+
+/**
+ * @codeCoverageIgnore
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class CoreMockObjectRepository extends \PHPUnit_Framework_TestCase implements MockObjectRepository {
+
+ /** @var MockObjectBuilder */
+ protected $builder;
+
+ /**
+ * @since 1.9
+ */
+ public function registerBuilder( MockObjectBuilder $builder ) {
+ $this->builder = $builder;
+ }
+
+ /**
+ * Returns a SemanticData object
+ *
+ * @since 1.9
+ *
+ * @return SemanticData
+ */
+ public function SemanticData() {
+
+ $semanticData = $this->getMockBuilder( 'SMW\SemanticData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $semanticData->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $semanticData;
+ }
+
+ /**
+ * Helper method that returns a CacheableResultCollector object
+ *
+ * @since 1.9
+ *
+ * @return CacheableResultCollector
+ */
+ public function CacheableResultCollector() {
+
+ // CacheableResultCollector is an abstract class therefore necessary methods
+ // are declared by default while other methods are only mocked if needed
+ // because setMethods overrides the original signature
+ $methods = [ 'cacheSetup', 'runCollector' ];
+
+ if ( $this->builder->hasValue( 'getResults' ) ) {
+ $methods[] = 'getResults';
+ }
+
+ $collector = $this->getMockBuilder( '\SMW\Store\CacheableResultCollector' )
+ ->setMethods( $methods )
+ ->getMock();
+
+ $collector->expects( $this->any() )
+ ->method( 'runCollector' )
+ ->will( $this->returnValue( $this->builder->setValue( 'runCollector' ) ) );
+
+ $collector->expects( $this->any() )
+ ->method( 'cacheSetup' )
+ ->will( $this->returnValue( $this->builder->setValue( 'cacheSetup' ) ) );
+
+ $collector->expects( $this->any() )
+ ->method( 'getResults' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getResults' ) ) );
+
+ return $collector;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return DependencyObject
+ */
+ public function DependencyObject() {
+
+ $methods = $this->builder->getInvokedMethods();
+
+ $dependencyObject = $this->getMockBuilder( 'SMW\DependencyObject' )
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $dependencyObject->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $dependencyObject;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return DependencyContainer
+ */
+ public function FakeDependencyContainer() {
+
+ $methods = $this->builder->getInvokedMethods();
+
+ $dependencyObject = $this->getMockBuilder( 'SMW\NullDependencyContainer' )
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $dependencyObject->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $dependencyObject;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return ParserData
+ */
+ public function ParserData() {
+
+ $methods = $this->builder->getInvokedMethods();
+
+ $parserData = $this->getMockBuilder( 'SMW\ParserData' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $parserData->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $parserData;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return Factbox
+ */
+ public function Factbox() {
+
+ $factbox = $this->getMockBuilder( '\SMW\Factbox\Factbox' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $factbox->expects( $this->any() )
+ ->method( 'isVisible' )
+ ->will( $this->returnValue( $this->builder->setValue( 'isVisible' ) ) );
+
+ $factbox->expects( $this->any() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getContent' ) ) );
+
+ return $factbox;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return SMWQuery
+ */
+ public function Query() {
+
+ $query = $this->getMockBuilder( 'SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ return $query;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return ContentParser
+ */
+ public function ContentParser() {
+
+ $contentParser = $this->getMockBuilder( '\SMW\ContentParser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $contentParser->expects( $this->any() )
+ ->method( 'getOutput' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getOutput', $this->builder->newObject( 'ParserOutput' ) ) ) );
+
+ $contentParser->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getErrors', [] ) ) );
+
+ $contentParser->expects( $this->any() )
+ ->method( 'getRevision' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getRevision', null ) ) );
+
+ return $contentParser;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return DataValue
+ * @throws OutOfBoundsException
+ */
+ public function DataValue() {
+
+ if ( !$this->builder->hasValue( 'DataValueType' ) ) {
+ throw new OutOfBoundsException( 'DataValueType is missing' );
+ }
+
+ $dataValue = $this->getMockBuilder( $this->builder->setValue( 'DataValueType' ) )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ if ( $method === 'DataValueType' ) {
+ continue;
+ }
+
+ $dataValue->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $dataValue;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return SMWQueryResult
+ */
+ public function QueryResult() {
+
+ $queryResult = $this->getMockBuilder( 'SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getErrors', [] ) ) );
+
+ // Word of caution, onConsecutiveCalls is used in order to ensure
+ // that a while() loop is not trapped in an infinite loop and returns
+ // a false at the end
+ $queryResult->expects( $this->any() )
+ ->method( 'getNext' )
+ ->will( $this->onConsecutiveCalls( $this->builder->setValue( 'getNext' ), false ) );
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $queryResult->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $queryResult;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return DIWikiPage
+ */
+ public function DIWikiPage() {
+
+ $diWikiPage = $this->getMockBuilder( '\SMW\DIWikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $diWikiPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getTitle' ) ) );
+
+ $diWikiPage->expects( $this->any() )
+ ->method( 'getDBkey' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getDBkey', $this->builder->newRandomString( 10, 'DIWikiPage-auto-dbkey' ) ) ) );
+
+ $diWikiPage->expects( $this->any() )
+ ->method( 'getPrefixedText' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getPrefixedText', $this->builder->newRandomString( 10, 'DIWikiPage-auto-prefixedText' ) ) ) );
+
+ $diWikiPage->expects( $this->any() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( SMWDataItem::TYPE_WIKIPAGE ) );
+
+ $diWikiPage->expects( $this->any() )
+ ->method( 'findPropertyTypeID' )
+ ->will( $this->returnValue( $this->builder->setValue( 'findPropertyTypeID', '_wpg' ) ) );
+
+ $diWikiPage->expects( $this->any() )
+ ->method( 'getSubobjectName' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getSubobjectName', '' ) ) );
+
+ return $diWikiPage;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return DIProperty
+ */
+ public function DIProperty() {
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property->expects( $this->any() )
+ ->method( 'findPropertyTypeID' )
+ ->will( $this->returnValue( $this->builder->setValue( 'findPropertyTypeID', '_wpg' ) ) );
+
+ $property->expects( $this->any() )
+ ->method( 'getKey' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getKey', '_wpg' ) ) );
+
+ $property->expects( $this->any() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( SMWDataItem::TYPE_PROPERTY ) );
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $property->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $property;
+ }
+
+ /**
+ * @note MockStore is based on the abstract Store class which avoids
+ * dependency on a specific Store implementation (SQLStore etc.), the mock
+ * object will allow to override necessary methods
+ *
+ * @since 1.9
+ *
+ * @return Store
+ */
+ public function Store() {
+
+ // SMW\Store is an abstract class, use setMethods to implement
+ // required abstract methods
+ $requiredAbstractMethods = [
+ 'setup',
+ 'drop',
+ 'getStatisticsTable',
+ 'getObjectIds',
+ 'refreshData',
+ 'getStatistics',
+ 'getQueryResult',
+ 'getPropertiesSpecial',
+ 'getUnusedPropertiesSpecial',
+ 'getWantedPropertiesSpecial',
+ 'getPropertyTables',
+ 'deleteSubject',
+ 'doDataUpdate',
+ 'changeTitle',
+ 'getProperties',
+ 'getInProperties',
+ 'getAllPropertySubjects',
+ 'getSQLConditions',
+ 'getSemanticData',
+ 'getPropertyValues',
+ 'getPropertySubjects',
+ 'refreshConceptCache',
+ 'deleteConceptCache',
+ 'getConceptCacheStatus',
+ 'clearData',
+ 'updateData'
+ ];
+
+ $methods = array_unique( array_merge( $requiredAbstractMethods, $this->builder->getInvokedMethods() ) );
+
+ $idTable = $this->getMockBuilder( 'stdClass' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getIdTable' ] )
+ ->getMock();
+
+ $idTable->expects( $this->any() )
+ ->method( 'getIdTable' )
+ ->will( $this->returnValue( 'smw_id_table_test' ) );
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( $methods )
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $idTable ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->builder->setCallback( 'getProperties', [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getInProperties' )
+ ->will( $this->builder->setCallback( 'getInProperties', [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getStatisticsTable' )
+ ->will( $this->returnValue( 'smw_statistics_table_test' ) );
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $store->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $store;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return TableDefinition
+ */
+ public function SQLStoreTableDefinition() {
+
+ $tableDefinition = $this->getMockBuilder( 'SMW\SQLStore\TableDefinition' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $tableDefinition->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $tableDefinition;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return SMWDIError
+ */
+ public function DIError() {
+
+ $errors = $this->getMockBuilder( 'SMWDIError' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $errors->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getErrors' ) ) );
+
+ return $errors;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return SMWDataItem
+ */
+ public function DataItem() {
+
+ $requiredMethods = [
+ 'getNumber',
+ 'getDIType',
+ 'getSortKey',
+ 'equals',
+ 'getSerialization',
+ ];
+
+ $methods = array_unique( array_merge( $requiredMethods, $this->builder->getInvokedMethods() ) );
+
+ $dataItem = $this->getMockBuilder( 'SMWDataItem' )
+ ->disableOriginalConstructor()
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $dataItem->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $dataItem;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return PrintRequest
+ */
+ public function PrintRequest() {
+
+ $printRequest = $this->getMockBuilder( 'SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getText', $this->builder->newRandomString( 10, 'Auto-printRequest' ) ) ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getLabel' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getLabel' ) ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getMode' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getMode', PrintRequest::PRINT_THIS ) ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getTypeID' ) ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getOutputFormat' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getOutputFormat' ) ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getParameter' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getParameter', 'center' ) ) );
+
+ return $printRequest;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return SMWResultArray
+ */
+ public function ResultArray() {
+
+ $resultArray = $this->getMockBuilder( 'SMWResultArray' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getPrintRequest' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getPrintRequest' ) ) );
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getContent' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getContent' ) ) );
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getNextDataValue' )
+ ->will( $this->onConsecutiveCalls( $this->builder->setValue( 'getNextDataValue' ), false ) );
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getNextDataItem' )
+ ->will( $this->onConsecutiveCalls( $this->builder->setValue( 'getNextDataItem' ), false ) );
+
+ return $resultArray;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return Description
+ */
+ public function QueryDescription() {
+
+ $requiredAbstractMethods = [
+ 'getQueryString',
+ 'isSingleton'
+ ];
+
+ $methods = array_unique( array_merge( $requiredAbstractMethods, $this->builder->getInvokedMethods() ) );
+
+ $queryDescription = $this->getMockBuilder( '\SMWDescription' )
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $queryDescription->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $queryDescription;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return PageInfoProvider
+ */
+ public function PageInfoProvider() {
+
+ $methods = $this->builder->getInvokedMethods();
+
+ $adapter = $this->getMockBuilder( 'SMW\PageInfoProvider' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $adapter->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $adapter;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/FakeQueryStore.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/FakeQueryStore.php
new file mode 100644
index 00000000..306f66ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/FakeQueryStore.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+use SMW\QueryEngine;
+use SMW\Store;
+use SMW\StoreAware;
+use SMWQuery;
+use SMWQueryResult;
+
+/**
+ * FIXME One would wish to have a FakeStore but instead SMWSQLStore3 is used in
+ * order to avoid to implement all abstract methods specified by SMW\Store
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group medium
+ * @group semantic-mediawiki-integration
+ * @group mediawiki-databaseless
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class FakeQueryStore implements QueryEngine, StoreAware {
+
+ protected $store;
+
+ public function setQueryResult( SMWQueryResult $queryResult ) {
+ $this->queryResult = $queryResult;
+ }
+
+ public function setStore( Store $store ) {
+ $this->store = $store;
+ }
+
+ // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.CodeAnalysis.UnusedFunctionParameter
+ public function getQueryResult( SMWQuery $query ) { // @codingStandardsIgnoreEnd
+ return $this->store->getQueryResult( $query );
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/IteratorMockBuilder.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/IteratorMockBuilder.php
new file mode 100644
index 00000000..721f4b36
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/IteratorMockBuilder.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+use RuntimeException;
+
+/**
+ * Convenience mock builder for Iterator classes
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class IteratorMockBuilder extends \PHPUnit_Framework_TestCase {
+
+ private $iteratorClass;
+ private $items = [];
+ private $methods = [];
+ private $counter = 0;
+
+ /**
+ * @since 2.0
+ *
+ * @param string $iteratorClass
+ *
+ * @return IteratorMockBuilder
+ */
+ public function setClass( $iteratorClass ) {
+ $this->iteratorClass = $iteratorClass;
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param array $items
+ *
+ * @return IteratorMockBuilder
+ */
+ public function with( array $items ) {
+ $this->items = $items;
+ return $this;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $methods
+ *
+ * @return IteratorMockBuilder
+ */
+ public function setMethods( array $methods ) {
+ $this->methods = $methods;
+ return $this;
+ }
+
+ /**
+ * @note When other methods called before the actual current/next then
+ * set the counter to ensure the starting point matches the expected
+ * InvokeCount.
+ *
+ * @since 2.5
+ *
+ * @param integer $num
+ *
+ * @return IteratorMockBuilder
+ */
+ public function incrementInvokedCounterBy( $num ) {
+ $this->counter += $num;
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return PHPUnit_Framework_MockObject_MockObject
+ * @throws RuntimeException
+ */
+ public function getMockForIterator() {
+
+ $instance = $this->getMockBuilder( $this->iteratorClass )
+ ->disableOriginalConstructor()
+ ->setMethods( $this->methods )
+ ->getMock();
+
+ if ( !$instance instanceof \Iterator ) {
+ throw new RuntimeException( "Instance is not an Iterator" );
+ }
+
+ $instance->expects( $this->at( $this->counter++ ) )
+ ->method( 'rewind' );
+
+ foreach ( $this->items as $key => $value ) {
+
+ $instance->expects( $this->at( $this->counter++ ) )
+ ->method( 'valid' )
+ ->will( $this->returnValue( true ) );
+
+ $instance->expects( $this->at( $this->counter++ ) )
+ ->method( 'current' )
+ ->will( $this->returnValue( $value ) );
+
+ $instance->expects( $this->at( $this->counter++ ) )
+ ->method( 'next' );
+ }
+
+ $instance->expects( $this->at( $this->counter++ ) )
+ ->method( 'valid' )
+ ->will( $this->returnValue( false ) );
+
+ return $instance;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return integer
+ */
+ public function getLastCounter() {
+ return $this->counter;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MediaWikiMockObjectRepository.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MediaWikiMockObjectRepository.php
new file mode 100644
index 00000000..24932f53
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MediaWikiMockObjectRepository.php
@@ -0,0 +1,517 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+/**
+ * @codeCoverageIgnore
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class MediaWikiMockObjectRepository extends \PHPUnit_Framework_TestCase implements MockObjectRepository {
+
+ /** @var MockObjectBuilder */
+ protected $builder;
+
+ /**
+ * @since 1.9
+ */
+ public function registerBuilder( MockObjectBuilder $builder ) {
+ $this->builder = $builder;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return User
+ */
+ public function User() {
+
+ $user = $this->getMockBuilder( 'User' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects( $this->any() )
+ ->method( 'getUserPage' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getUserPage' ) ) );
+
+ return $user;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return ParserOptions
+ */
+ public function ParserOptions() {
+
+ $parserOptions = $this->getMockBuilder( 'ParserOptions' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parserOptions->expects( $this->any() )
+ ->method( 'getTargetLanguage' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getTargetLanguage' ) ) );
+
+ return $parserOptions;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return ParserOutput
+ */
+ public function ParserOutput() {
+
+ $parserOutput = $this->getMockBuilder( 'ParserOutput' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $parserOutput->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $parserOutput;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return WikiPage
+ */
+ public function WikiPage() {
+
+ $wikiPage = $this->getMockBuilder( 'WikiPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $wikiPage->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $wikiPage;
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @return WikiFilePage
+ */
+ public function WikiFilePage() {
+
+ $wikiPage = $this->getMockBuilder( 'WikiFilePage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $wikiPage->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $wikiPage;
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @return File
+ */
+ public function File() {
+
+ $wikiPage = $this->getMockBuilder( 'File' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $wikiPage->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $wikiPage;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return Revision
+ */
+ public function Revision() {
+
+ $revision = $this->getMockBuilder( 'Revision' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $revision->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $revision;
+ }
+
+ /**
+ * @note This mock object avoids the involvement of LinksUpdate (which
+ * requires DB access) and returns a randomized LatestRevID/ArticleID
+ *
+ * @since 1.9
+ *
+ * @return Title
+ */
+ public function Title() {
+
+ // When interacting with a "real" Parser object, the Parser expects in
+ // in 1.21+ a content model to be present while in MW 1.19/1.20 such
+ // object is not required. In order to avoid operational obstruction a
+ // model is set as default and can if necessary individually be overridden
+ $contentModel = defined( 'CONTENT_MODEL_WIKITEXT' ) ? CONTENT_MODEL_WIKITEXT : null;
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $this->any() )
+ ->method( 'getDBkey' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getDBkey', $this->builder->newRandomString( 10, 'Title-auto-dbkey' ) ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getInterwiki' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getInterwiki', '' ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getArticleID' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getArticleID', rand( 10, 10000 ) ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getNamespace' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getNamespace', NS_MAIN ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isKnown' )
+ ->will( $this->returnValue( $this->builder->setValue( 'exists' ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( $this->builder->setValue( 'exists' ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getLatestRevID' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getLatestRevID', rand( 10, 5000 ) ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getFirstRevision' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getFirstRevision' ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getText' ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getPrefixedText' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getPrefixedText', $this->builder->newRandomString( 10, 'Title-auto-prefixedtext' ) ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $this->returnValue( $this->builder->setValue( 'isSpecialPage', false ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isSpecial' )
+ ->will( $this->returnValue( $this->builder->setValue( 'isSpecial', false ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isDeleted' )
+ ->will( $this->returnValue( $this->builder->setValue( 'isDeleted', false ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getContentModel' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getContentModel', $contentModel ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getPageLanguage' ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'isRedirect' )
+ ->will( $this->returnValue( $this->builder->setValue( 'isRedirect', false ) ) );
+
+ $title->expects( $this->any() )
+ ->method( 'inNamespace' )
+ ->will( $this->builder->setCallback( 'inNamespace' ) );
+
+ return $title;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return Skin
+ */
+ public function Skin() {
+
+ $skin = $this->getMockBuilder( 'Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $skin->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $skin;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return SkinTemplate
+ */
+ public function SkinTemplate() {
+
+ $skinTemplate = $this->getMockBuilder( 'SkinTemplate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $skinTemplate->expects( $this->any() )
+ ->method( 'getSkin' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getSkin' ) ) );
+
+ return $skinTemplate;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return Parser
+ */
+ public function Parser() {
+
+ $parser = $this->getMockBuilder( 'Parser' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $parser->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $parser;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return LinksUpdate
+ */
+ public function LinksUpdate() {
+
+ $linksUpdate = $this->getMockBuilder( 'LinksUpdate' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $linksUpdate->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $linksUpdate;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return OutputPage
+ */
+ public function OutputPage() {
+
+ $outputPage = $this->getMockBuilder( 'OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->any() )
+ ->method( 'getTitle' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getTitle' ) ) );
+
+ $outputPage->expects( $this->any() )
+ ->method( 'getContext' )
+ ->will( $this->returnValue( $this->builder->setValue( 'getContext' ) ) );
+
+ $outputPage->expects( $this->any() )
+ ->method( 'addModules' )
+ ->will( $this->returnValue( $this->builder->setValue( 'addModules' ) ) );
+
+ $outputPage->expects( $this->any() )
+ ->method( 'addLink' )
+ ->will( $this->returnValue( $this->builder->setValue( 'addLink' ) ) );
+
+ // getHeadLinksArray doesn't exist in MW 1.19
+ $outputPage->expects( $this->any() )
+ ->method( 'getHeadLinksArray' )
+ ->will( $this->builder->setCallback( 'getHeadLinksArray' ) );
+
+ return $outputPage;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return DatabaseBase
+ */
+ public function DatabaseBase() {
+
+ // DatabaseBase is an abstract class, use setMethods to implement
+ // required abstract methods
+ $requiredAbstractMethods = [
+ 'selectField',
+ 'doQuery',
+ 'getType',
+ 'open',
+ 'fetchObject',
+ 'fetchRow',
+ 'numRows',
+ 'numFields',
+ 'fieldName',
+ 'insertId',
+ 'dataSeek',
+ 'lastErrno',
+ 'lastError',
+ 'fieldInfo',
+ 'indexInfo',
+ 'affectedRows',
+ 'strencode',
+ 'getSoftwareLink',
+ 'getServerVersion',
+ 'closeConnection'
+ ];
+
+ $methods = array_unique( array_merge( $requiredAbstractMethods, $this->builder->getInvokedMethods() ) );
+
+ $databaseBase = $this->getMockBuilder( 'DatabaseBase' )
+ ->disableOriginalConstructor()
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $this->builder->getInvokedMethods() as $method ) {
+
+ $databaseBase->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $databaseBase;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return Content
+ */
+ public function Content() {
+
+ $methods = $this->builder->getInvokedMethods();
+
+ $content = $this->getMockBuilder( 'Content' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $content->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $content;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return ContentHandler
+ */
+ public function ContentHandler() {
+
+ $requiredAbstractMethods = [
+ 'serializeContent',
+ 'unserializeContent',
+ 'makeEmptyContent'
+ ];
+
+ $methods = array_unique( array_merge( $requiredAbstractMethods, $this->builder->getInvokedMethods() ) );
+
+ $contentHandler = $this->getMockBuilder( 'ContentHandler' )
+ ->disableOriginalConstructor()
+ ->setMethods( $methods )
+ ->getMock();
+
+ foreach ( $methods as $method ) {
+
+ $contentHandler->expects( $this->any() )
+ ->method( $method )
+ ->will( $this->builder->setCallback( $method ) );
+
+ }
+
+ return $contentHandler;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return RequestContext
+ */
+ public function RequestContext() {
+
+ $requestContext = $this->getMockForAbstractClass( 'RequestContext' );
+
+ return $requestContext;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return Language
+ */
+ public function Language() {
+
+ $language = $this->getMockBuilder( 'Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ return $language;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectBuilder.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectBuilder.php
new file mode 100644
index 00000000..473c9602
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectBuilder.php
@@ -0,0 +1,195 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+use InvalidArgumentException;
+use OutOfBoundsException;
+use SMW\ObjectDictionary;
+use SMW\Options;
+
+/**
+ * @codeCoverageIgnore
+ *
+ * MockObject builder provides methods that are being used by the mock repository
+ * to define and create a mock object
+ *
+ * $title = new MockObjectBuilder()
+ * $title->newObject( 'Foo', array(
+ * 'Bar' => ...
+ * ) )
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class MockObjectBuilder extends \PHPUnit_Framework_TestCase {
+
+ /** @var ObjectDictionary */
+ protected $configuration;
+
+ /** @var MockObjectRepository */
+ protected $repository = [];
+
+ /**
+ * @since 1.9
+ *
+ * @param MockObjectRepository|null $repository
+ */
+ public function __construct( MockObjectRepository $repository = null ) {
+
+ if ( $repository === null ) {
+ $repository = new CoreMockObjectRepository();
+ }
+
+ $this->registerRepository( $repository );
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @param MockObjectRepository $repository
+ */
+ public function registerRepository( MockObjectRepository $repository ) {
+ $this->repository[] = $repository;
+ }
+
+ /**
+ * Helper method that stores configuration settings
+ *
+ * @since 1.9
+ *
+ * @param $objectName
+ * @param $objectArguments
+ *
+ * @return mixed
+ */
+ public function newObject( $objectName, $objectArguments = [] ) {
+
+ if ( !is_string( $objectName ) ) {
+ throw new InvalidArgumentException( "Object name is not a string" );
+ }
+
+ if ( $objectArguments !== [] && !is_array( $objectArguments ) ) {
+ throw new InvalidArgumentException( "Arguments are not an array type" );
+ }
+
+ $repository = $this->findRepositoryForObject( $objectName );
+
+ if ( !$repository instanceof MockObjectRepository ) {
+ throw new OutOfBoundsException( "{$objectName} method doesn't exists" );
+ }
+
+ $repository->registerBuilder( $this );
+ $this->setupConfiguration( $objectArguments );
+
+ return $repository->{$objectName}();
+ }
+
+ /**
+ * Returns invoked configuration keys
+ *
+ * @since 1.9
+ *
+ * @return array
+ */
+ public function getInvokedMethods() {
+ return array_keys( $this->configuration->getOptions() );
+ }
+
+ /**
+ * Helper method that returns a random string
+ *
+ * @since 1.9
+ *
+ * @param $length
+ * @param $prefix identify a specific random string during testing
+ *
+ * @return string
+ */
+ public function newRandomString( $length = 10, $prefix = null ) {
+ return $prefix . ( $prefix ? '-' : '' ) . substr( str_shuffle( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, $length );
+ }
+
+ /**
+ * Whether the configuration is known
+ *
+ * @since 1.9
+ *
+ * @param $key
+ *
+ * @return boolean
+ */
+ public function hasValue( $key ) {
+ return $this->configuration->has( $key );
+ }
+
+ /**
+ * Sets value
+ *
+ * @since 1.9
+ *
+ * @param $key
+ * @param $default
+ *
+ * @return mixed|null
+ */
+ public function setValue( $key, $default = null ) {
+ return $this->configuration->has( $key ) ? $this->configuration->get( $key ) : $default;
+ }
+
+ /**
+ * Determine callback function otherwise return simple value
+ *
+ * @since 1.9
+ *
+ * @param $key
+ * @param $default
+ *
+ * @return mixed|null
+ */
+ public function setCallback( $key, $default = null ) {
+ return is_callable( $this->setValue( $key ) ) ? $this->returnCallback( $this->setValue( $key ) ) : $this->returnValue( $this->setValue( $key, $default ) );
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @param $objectName
+ *
+ * @return MockObjectRepository|null
+ */
+ protected function findRepositoryForObject( $objectName ) {
+
+ foreach ( $this->repository as $repository ) {
+ if ( method_exists( $repository, $objectName ) ) {
+ return $repository;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @param $config
+ */
+ protected function setupConfiguration( $config ) {
+
+ $configuration = new Options( $config );
+
+ if ( $this->configuration instanceof Options ) {
+ return $this->configuration = new Options(
+ array_merge( $this->configuration->getOptions(), $configuration->getOptions() )
+ );
+ }
+
+ $this->configuration = $configuration;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectRepository.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectRepository.php
new file mode 100644
index 00000000..b9bdb213
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockObjectRepository.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+/**
+ * Interface describing a MockObjectRepository object
+ *
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+interface MockObjectRepository {
+
+ /**
+ * Returns a DIProperty object
+ *
+ * @since 1.9
+ */
+ public function registerBuilder( MockObjectBuilder $builder );
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockSuperUser.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockSuperUser.php
new file mode 100644
index 00000000..cb91e3cb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockSuperUser.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+use User;
+
+/**
+ * Instantiate a SuperUser in order to be able to do everything
+ *
+ * @since 1.9
+ *
+ * @file
+ *
+ * @licence GNU GPL v2+
+ */
+
+/**
+ * Instantiate a SuperUser in order to be able to do everything.
+ * Borrowed from Translate/EducationProgram extension :-)
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @codeCoverageIgnore
+ */
+class MockSuperUser extends User {
+ public function getId() {
+ return 666;
+ }
+
+ public function getName() {
+ return 'SuperUser';
+ }
+
+ public function isAllowed( $right = '' ) {
+ return true;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockTitle.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockTitle.php
new file mode 100644
index 00000000..57626237
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Mock/MockTitle.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SMW\Tests\Utils\Mock;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class MockTitle extends \PHPUnit_Framework_TestCase {
+
+ public static function buildMock( $text = __METHOD__ ) {
+
+ $instance = new self();
+
+ $contentModel = defined( 'CONTENT_MODEL_WIKITEXT' ) ? CONTENT_MODEL_WIKITEXT : null;
+
+ $title = $instance->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $title->expects( $instance->any() )
+ ->method( 'getDBkey' )
+ ->will( $instance->returnValue( str_replace( ' ', '_', $text ) ) );
+
+ $title->expects( $instance->any() )
+ ->method( 'getPrefixedDBkey' )
+ ->will( $instance->returnValue( str_replace( ' ', '_', $text ) ) );
+
+ $title->expects( $instance->any() )
+ ->method( 'getContentModel' )
+ ->will( $instance->returnValue( $contentModel ) );
+
+ return $title;
+ }
+
+ public static function buildMockForMainNamespace( $text = __METHOD__ ) {
+
+ $instance = new self();
+
+ $title = $instance->buildMock( $text );
+
+ $title->expects( $instance->any() )
+ ->method( 'getNamespace' )
+ ->will( $instance->returnValue( NS_MAIN ) );
+
+ $title->expects( $instance->any() )
+ ->method( 'getArticleID' )
+ ->will( $instance->returnValue( 9001 ) );
+
+ $title->expects( $instance->any() )
+ ->method( 'isSpecialPage' )
+ ->will( $instance->returnValue( false ) );
+
+ return $title;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwApiFactory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwApiFactory.php
new file mode 100644
index 00000000..24d9412d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwApiFactory.php
@@ -0,0 +1,87 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use ApiMain;
+use ApiResult;
+use FauxRequest;
+use RequestContext;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use WebRequest;
+
+/**
+ * Class contains Api related request methods
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class MwApiFactory {
+
+ /**
+ * @param array $params
+ *
+ * @return ApiMain
+ */
+ public function newApiMain( array $params ) {
+ return new ApiMain( $this->newRequestContext( $params ), true );
+ }
+
+ /**
+ * @param array $params
+ *
+ * @return ApiResult
+ */
+ public function newApiResult( array $params ) {
+
+ if ( version_compare( $GLOBALS['wgVersion'], '1.25', '<' ) ) {
+ return new ApiResult( $this->newApiMain( $params ) );
+ }
+
+ $result = new ApiResult( 5 );
+
+ $errorFormatter = new \ApiErrorFormatter_BackCompat( $result );
+ $result->setErrorFormatter( $errorFormatter );
+
+ return $result;
+ }
+
+ /**
+ * Returns Api results
+ *
+ * The returned value is an array containing
+ * - the result data (array)
+ *
+ * @param array $params
+ *
+ * @return array
+ */
+ public function doApiRequest( array $params ) {
+
+ $api = $this->newApiMain( $params );
+ $api->execute();
+
+ if ( method_exists( $api->getResult(), 'getResultData' ) ) {
+ return $api->getResult()->getResultData();
+ }
+
+ return $api->getResultData();
+ }
+
+ private function newRequestContext( $request = [] ) {
+
+ $context = new RequestContext();
+
+ if ( $request instanceof WebRequest ) {
+ $context->setRequest( $request );
+ } else {
+ $context->setRequest( new FauxRequest( $request, true ) );
+ }
+
+ $context->setUser( new MockSuperUser() );
+
+ return $context;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwHooksHandler.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwHooksHandler.php
new file mode 100644
index 00000000..2e842ec1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/MwHooksHandler.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use RuntimeException;
+use SMW\MediaWiki\Hooks\HookRegistry;
+
+/**
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class MwHooksHandler {
+
+ /**
+ * @var HookRegistry
+ */
+ private $hookRegistry = null;
+
+ private $wgHooks = [];
+ private $inTestRegisteredHooks = [];
+
+ private $listOfSmwHooks = [
+ 'SMWStore::updateDataBefore',
+
+ // Those shoudl not be disabled so that extension used
+ // by a test will run the registration in case an instance
+ // is cleared
+ // 'smwInitDatatypes',
+ // 'SMW::DataType::initTypes',
+
+ 'smwInitProperties',
+ 'SMW::Property::initProperties',
+ 'SMW::Factbox::BeforeContentGeneration',
+ 'SMW::SQLStore::updatePropertyTableDefinitions',
+ 'SMW::Store::BeforeQueryResultLookupComplete',
+ 'SMW::Store::AfterQueryResultLookupComplete',
+ 'SMW::SQLStore::BeforeChangeTitleComplete',
+ 'SMW::SQLStore::BeforeDeleteSubjectComplete',
+ 'SMW::SQLStore::AfterDeleteSubjectComplete',
+ 'SMW::Parser::BeforeMagicWordsFinder',
+ 'SMW::SQLStore::BeforeDataRebuildJobInsert',
+ 'SMW::SQLStore::AddCustomFixedPropertyTables',
+ 'SMW::SQLStore::AfterDataUpdateComplete',
+ 'SMW::Browse::AfterIncomingPropertiesLookupComplete',
+ 'SMW::Browse::BeforeIncomingPropertyValuesFurtherLinkCreate'
+ ];
+
+ /**
+ * @since 2.0
+ *
+ * @return MwHooksHandler
+ */
+ public function deregisterListedHooks() {
+
+ $listOfHooks = array_merge(
+ $this->listOfSmwHooks,
+ $this->getHookRegistry()->getHandlerList()
+ );
+
+ foreach ( $listOfHooks as $hook ) {
+
+ // MW 1.19
+ if ( method_exists( 'Hooks', 'clear' ) ) {
+ \Hooks::clear( $hook );
+ }
+
+ if ( !isset( $GLOBALS['wgHooks'][$hook] ) ) {
+ continue;
+ }
+
+ $this->wgHooks[$hook] = $GLOBALS['wgHooks'][$hook];
+ $GLOBALS['wgHooks'][$hook] = [];
+ }
+
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return MwHooksHandler
+ */
+ public function restoreListedHooks() {
+
+ foreach ( $this->inTestRegisteredHooks as $hook ) {
+ unset( $GLOBALS['wgHooks'][$hook] );
+ }
+
+ foreach ( $this->wgHooks as $hook => $definition ) {
+ $GLOBALS['wgHooks'][$hook] = $definition;
+ unset( $this->wgHooks[$hook] );
+ }
+
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return MwHooksHandler
+ */
+ public function register( $name, callable $callback ) {
+
+ $listOfHooks = array_merge(
+ $this->listOfSmwHooks,
+ $this->getHookRegistry()->getHandlerList()
+ );
+
+ if ( !in_array( $name, $listOfHooks ) ) {
+ throw new RuntimeException( "$name is not listed as registrable hook" );
+ }
+
+ $this->inTestRegisteredHooks[] = $name;
+ $GLOBALS['wgHooks'][$name][] = $callback;
+
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return MwHooksHandler
+ */
+ public function invokeHooksFromRegistry() {
+ $this->getHookRegistry()->register();
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return HookRegistry
+ */
+ public function getHookRegistry() {
+
+ if ( $this->hookRegistry === null ) {
+ $this->hookRegistry = new HookRegistry( $GLOBALS, '' );
+ }
+
+ return $this->hookRegistry;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Page/PageEditor.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Page/PageEditor.php
new file mode 100644
index 00000000..b09bf5d4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Page/PageEditor.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace SMW\Tests\Utils\Page;
+
+use Revision;
+use RuntimeException;
+use Title;
+use WikiPage;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ */
+class PageEditor {
+
+ /**
+ * @var WikiPage|null
+ */
+ private $page = null;
+
+ /**
+ * @since 2.1
+ *
+ * @return WikiPage
+ * @throws RuntimeException
+ */
+ public function getPage() {
+
+ if ( $this->page instanceof WikiPage ) {
+ return $this->page;
+ }
+
+ throw new RuntimeException( 'Expected a valid WikiPage instance.' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param Title $title
+ *
+ * @return PageEditor
+ */
+ public function editPage( Title $title ) {
+ $this->page = new WikiPage( $title );
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $pageContent
+ * @param string $editMessage
+ *
+ * @return PageEditor
+ */
+ public function doEdit( $pageContent = '', $editMessage = '' ) {
+
+ if ( class_exists( 'WikitextContent' ) ) {
+ $content = new \WikitextContent( $pageContent );
+
+ $this->getPage()->doEditContent(
+ $content,
+ $editMessage
+ );
+
+ } else {
+ $this->getPage()->doEdit( $pageContent, $editMessage );
+ }
+
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function getEditInfo() {
+
+ if ( class_exists( 'WikitextContent' ) ) {
+
+ $content = $this->getPage()->getRevision()->getContent();
+ $format = $content->getContentHandler()->getDefaultFormat();
+
+ return $this->getPage()->prepareContentForEdit(
+ $content,
+ null,
+ null,
+ $format
+ );
+ }
+
+ if ( method_exists( $this->getPage()->getRevision(), 'getContent' ) ) {
+ $text = $this->getPage()->getRevision()->getContent( Revision::RAW );
+ } else {
+ $text = $this->getPage()->getRevision()->getRawText();
+ }
+ return $this->getPage()->prepareTextForEdit(
+ $text,
+ null,
+ null
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageCreator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageCreator.php
new file mode 100644
index 00000000..bbf34cf5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageCreator.php
@@ -0,0 +1,161 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use Revision;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use Title;
+use UnexpectedValueException;
+
+/**
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class PageCreator {
+
+ /**
+ * @var null
+ */
+ protected $page = null;
+
+ /**
+ * @since 1.9.1
+ *
+ * @return WikiPage
+ * @throws UnexpectedValueException
+ */
+ public function getPage() {
+
+ if ( $this->page instanceof \WikiPage ) {
+ return $this->page;
+ }
+
+ throw new UnexpectedValueException( 'Expected a WikiPage instance, use createPage first' );
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param Title $title
+ * @param string $editContent
+ * @param string $pageContentLanguage
+ *
+ * @return PageCreator
+ */
+ public function createPage( Title $title, $editContent = '', $pageContentLanguage = '' ) {
+
+ if ( $pageContentLanguage !== '' ) {
+ \Hooks::register( 'PageContentLanguage', function( $titleByHook, &$pageLang ) use( $title, $pageContentLanguage ) {
+
+ // Only change the pageContentLanguage for the selected page
+ if ( $title->getPrefixedDBKey() === $titleByHook->getPrefixedDBKey() ) {
+ $pageLang = $pageContentLanguage;
+ }
+
+ // MW 1.19
+ return true;
+ } );
+ }
+
+ $this->page = new \WikiPage( $title );
+
+ if ( $editContent === '' ) {
+ $editContent = 'Content of ' . $title->getFullText();
+ }
+
+ $editMessage = 'SMW system test: create page';
+
+ return $this->doEdit( $editContent, $editMessage );
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param string $pageContent
+ * @param string $editMessage
+ *
+ * @return PageCreator
+ */
+ public function doEdit( $pageContent = '', $editMessage = '' ) {
+
+ if ( class_exists( 'ContentHandler' ) ) {
+ $content = \ContentHandler::makeContent(
+ $pageContent,
+ $this->getPage()->getTitle()
+ );
+
+ $this->getPage()->doEditContent(
+ $content,
+ $editMessage
+ );
+
+ } else {
+ $this->getPage()->doEdit( $pageContent, $editMessage );
+ }
+
+ TestEnvironment::executePendingDeferredUpdates();
+
+ return $this;
+ }
+
+ /**
+ * @since 2.3
+ *
+ * @param Title $target
+ * @param boolean $isRedirect
+ *
+ * @return PageCreator
+ */
+ public function doMoveTo( Title $target, $isRedirect = true ) {
+
+ $reason = "integration test";
+ $source = $this->getPage()->getTitle();
+
+ if ( class_exists( '\MovePage' ) ) {
+ $mp = new \MovePage( $source, $target );
+ $status = $mp->move( new MockSuperUser(), $reason, $isRedirect );
+ } else {
+ // deprecated since 1.25, use the MovePage class instead
+ $status = $source->moveTo( $target, false, $reason, $isRedirect );
+ }
+
+ TestEnvironment::executePendingDeferredUpdates();
+
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return EditInfo
+ */
+ public function getEditInfo() {
+
+ $revision = $this->getPage()->getRevision();
+
+ if ( class_exists( 'ContentHandler' ) ) {
+
+ $content = $revision->getContent();
+ $format = $content->getContentHandler()->getDefaultFormat();
+
+ return $this->getPage()->prepareContentForEdit(
+ $content,
+ null,
+ null,
+ $format
+ );
+ }
+
+ $text = method_exists( $revision, 'getContent' ) ? $revision->getContent( Revision::RAW ) : $revision->getRawText();
+
+ return $this->getPage()->prepareTextForEdit(
+ $text,
+ null,
+ null
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageDeleter.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageDeleter.php
new file mode 100644
index 00000000..cebc13c1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageDeleter.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use SMW\DIWikiPage;
+use SMW\Tests\TestEnvironment;
+use Title;
+use WikiPage;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ */
+class PageDeleter {
+
+ /**
+ * @var TestEnvironment
+ */
+ private $testEnvironment;
+
+ /**
+ * @since 2.4
+ */
+ public function __construct() {
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ /**
+ * @since 1.9.1
+ */
+ public function deletePage( Title $title ) {
+ $page = new WikiPage( $title );
+ $page->doDeleteArticle( 'SMW system test: delete page' );
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param array $poolOfPages
+ */
+ public function doDeletePoolOfPages( array $poolOfPages ) {
+
+ foreach ( $poolOfPages as $page ) {
+
+ if ( $page instanceof WikiPage || $page instanceof DIWikiPage ) {
+ $page = $page->getTitle();
+ }
+
+ if ( is_string( $page ) ) {
+ $page = Title::newFromText( $page );
+ }
+
+ if ( !$page instanceof Title ) {
+ continue;
+ }
+
+ $this->deletePage( $page );
+ }
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageReader.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageReader.php
new file mode 100644
index 00000000..638cc4c3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageReader.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use Revision;
+use TextContent;
+use Title;
+use UnexpectedValueException;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class PageReader {
+
+ /**
+ * @var WikiPage
+ */
+ private $page = null;
+
+ /**
+ * @since 2.1
+ *
+ * @return WikiPage
+ * @throws UnexpectedValueException
+ */
+ public function getPage() {
+
+ if ( $this->page instanceof \WikiPage ) {
+ return $this->page;
+ }
+
+ throw new UnexpectedValueException( 'Expected a WikiPage instance, use createPage first' );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param Title $title
+ *
+ * @return text
+ */
+ public function getContentAsText( Title $title ) {
+
+ $this->page = new \WikiPage( $title );
+
+ if ( method_exists( $this->page, 'getContent' ) ) {
+ $content = $this->page->getContent();
+
+ if ( $content instanceof TextContent ) {
+ return $content->getNativeData();
+ } else {
+ return '';
+ }
+ }
+
+ return $this->page->getText();
+ }
+
+ /**
+ * @since 2.2
+ */
+ public function getEditInfo( Title $title ) {
+
+ $this->page = new \WikiPage( $title );
+
+ if ( class_exists( 'WikitextContent' ) ) {
+
+ $content = $this->page->getRevision()->getContent();
+ $format = $content->getContentHandler()->getDefaultFormat();
+
+ return $this->page->prepareContentForEdit(
+ $content,
+ null,
+ null,
+ $format
+ );
+ }
+
+ if ( method_exists( $this->getPage()->getRevision(), 'getContent' ) ) {
+ $text = $this->getPage()->getRevision()->getContent( Revision::RAW );
+ } else {
+ $text = $this->getPage()->getRevision()->getRawText();
+ }
+ return $this->page->prepareTextForEdit(
+ $text,
+ null,
+ null
+ );
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param Title $title
+ *
+ * @return ParserOutput|null
+ */
+ public function getParserOutputFromEdit( Title $title ) {
+ return $this->getEditInfo( $title )->output;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageRefresher.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageRefresher.php
new file mode 100644
index 00000000..05c74776
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/PageRefresher.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use RuntimeException;
+use SMW\ApplicationFactory;
+use SMW\ContentParser;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\UpdateJob;
+use Title;
+use WikiPage;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ */
+class PageRefresher {
+
+ /**
+ * @since 2.0
+ *
+ * @param mixed $title
+ *
+ * @return PageRefresher
+ */
+ public function doRefresh( $title ) {
+
+ if ( $title instanceof WikiPage || $title instanceof DIWikiPage ) {
+ $title = $title->getTitle();
+ }
+
+ if ( !$title instanceof Title ) {
+ throw new RuntimeException( 'Expected a title instance' );
+ }
+
+ $contentParser = new ContentParser( $title );
+
+ $parserData = ApplicationFactory::getInstance()->newParserData(
+ $title,
+ $contentParser->parse()->getOutput()
+ );
+
+ $parserData->updateStore();
+
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param array $pages
+ *
+ * @return PageRefresher
+ */
+ public function doRefreshPoolOfPages( array $pages ) {
+ foreach ( $pages as $page ) {
+ $this->doRefreshByUpdateJob( $page );
+ }
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param mixed $title
+ *
+ * @return PageRefresher
+ */
+ public function doRefreshByUpdateJob( $title ) {
+
+ if ( $title instanceof WikiPage || $title instanceof DIWikiPage ) {
+ $title = $title->getTitle();
+ }
+
+ if ( is_string( $title ) ) {
+ $title = Title::newFromText( $title );
+ }
+
+ if ( !$title instanceof Title ) {
+ throw new RuntimeException( 'Expected a title instance' );
+ }
+
+ $job = new UpdateJob( $title );
+ $job->run();
+
+ return $this;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ParserFactory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ParserFactory.php
new file mode 100644
index 00000000..c0317278
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/ParserFactory.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use Parser;
+use ParserOptions;
+use SMW\DIWikiPage;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use Title;
+use User;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ */
+class ParserFactory {
+
+ public static function create( $title, User $user = null ) {
+
+ if ( is_string( $title ) ) {
+ $title = Title::newFromText( $title );
+ }
+
+ if ( $title instanceof DIWikiPage ) {
+ $title = $title->getTitle();
+ }
+
+ return self::newFromTitle( $title, $user );
+ }
+
+ public static function newFromTitle( Title $title, User $user = null ) {
+
+ if ( $user === null ) {
+ $user = new MockSuperUser();
+ }
+
+ // $wikiPage = new \WikiPage( $title );
+ // $wikiPage->makeParserOptions( $user );
+
+ $parser = new Parser( $GLOBALS['wgParserConf'] );
+ $parser->setTitle( $title );
+ $parser->setUser( $user );
+ $parser->Options( new ParserOptions( $user ) );
+ $parser->clearState();
+
+ return $parser;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/JobQueueRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/JobQueueRunner.php
new file mode 100644
index 00000000..29e124db
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/JobQueueRunner.php
@@ -0,0 +1,156 @@
+<?php
+
+namespace SMW\Tests\Utils\Runners;
+
+use Job;
+use JobQueueGroup;
+use SMW\Connection\ConnectionProvider as IConnectionProvider;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\Utils\Connection\ConnectionProvider;
+
+/**
+ * Partly copied from the MW 1.19 RunJobs maintenance script
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ */
+class JobQueueRunner {
+
+ protected $type = null;
+ protected $status = [];
+ protected $connectionProvider = null;
+
+ /**
+ * @var TestEnvironment
+ */
+ private $testEnvironment;
+
+ /**
+ * @since 1.9.2
+ *
+ * @param string|null $type
+ * @param IConnectionProvider|null $connectionProvider
+ */
+ public function __construct( $type = null, IConnectionProvider $connectionProvider = null ) {
+ $this->type = $type;
+ $this->connectionProvider = $connectionProvider;
+
+ if ( $this->connectionProvider === null ) {
+ $this->connectionProvider = new ConnectionProvider();
+ }
+
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $type
+ *
+ * @return JobQueueRunner
+ */
+ public function setType( $type ) {
+ $this->type = $type;
+ return $this;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param IConnectionProvider $connectionProvider
+ *
+ * @return JobQueueRunner
+ */
+ public function setConnectionProvider( IConnectionProvider $connectionProvider ) {
+ $this->connectionProvider = $connectionProvider;
+ return $this;
+ }
+
+ /**
+ * @since 1.9.2
+ */
+ public function run() {
+
+ $conds = '';
+ $connection = $this->connectionProvider->getConnection();
+
+ if ( $this->type !== null ) {
+ $conds = "job_cmd = " . $connection->addQuotes( $this->type );
+ }
+
+ while ( $connection->selectField( 'job', 'job_id', $conds, __METHOD__ ) ) {
+
+ $job = $this->type === null ? $this->pop() : $this->pop_type( $this->type );
+
+ if ( !$job ) {
+ break;
+ }
+
+ wfWaitForSlaves();
+
+ $this->status[] = [
+ 'type' => $job->command,
+ 'status' => $job->run()
+ ];
+ }
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public function deleteAllJobs() {
+
+ $conditions = '*';
+ $connection = $this->connectionProvider->getConnection();
+
+ if ( $this->type !== null ) {
+ $conditions = "job_cmd = " . $connection->addQuotes( $this->type );
+ }
+
+ $connection->delete(
+ 'job',
+ $conditions,
+ __METHOD__
+ );
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @return array
+ */
+ public function getStatus() {
+ return $this->status;
+ }
+
+ /**
+ * @see https://gerrit.wikimedia.org/r/#/c/162009/
+ */
+ private function pop() {
+ $offset = 0;
+
+ if ( class_exists( 'JobQueueGroup' ) ) {
+ return JobQueueGroup::singleton()->pop();
+ }
+
+ return Job::pop( $offset );
+ }
+
+ /**
+ * @see https://gerrit.wikimedia.org/r/#/c/162009/
+ */
+ public function pop_type( $type ) {
+
+ if ( class_exists( 'JobQueueGroup' ) ) {
+ return JobQueueGroup::singleton()->get( $type )->pop();
+ }
+
+ return Job::pop_type( $type );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/MaintenanceRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/MaintenanceRunner.php
new file mode 100644
index 00000000..17741cea
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/MaintenanceRunner.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace SMW\Tests\Utils\Runners;
+
+use DomainException;
+use Onoi\MessageReporter\MessageReporterAwareTrait;
+use RuntimeException;
+use SMW\ApplicationFactory;
+
+/**
+ * Running maintenance scripts via phpunit is not really possible but instead
+ * this class allows to execute script related classes that are equivalent to:
+ * `php rebuildData.php --< myOptions >`
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class MaintenanceRunner {
+
+ use MessageReporterAwareTrait;
+
+ protected $maintenanceClass = null;
+ protected $options = [];
+ protected $output = null;
+ protected $quiet = false;
+
+ /**
+ * @since 1.9.2
+ *
+ * @param string $maintenanceClass
+ * @param array $options
+ */
+ public function __construct( $maintenanceClass, $options = [] ) {
+ $this->maintenanceClass = $maintenanceClass;
+ $this->options = $options;
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @param array $options
+ *
+ * @return MaintenanceRunner
+ */
+ public function setOptions( array $options ) {
+ $this->options = $options;
+ return $this;
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @return MaintenanceRunner
+ */
+ public function setQuiet() {
+ $this->options['quiet'] = true;
+ return $this;
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @return boolean
+ * @throws RuntimeException
+ * @throws DomainException
+ */
+ public function run() {
+
+ if ( !class_exists( $this->maintenanceClass ) ) {
+ throw new RuntimeException( "Expected a valid {$this->maintenanceClass} class" );
+ }
+
+ $obLevel = ob_get_level();
+
+ // Avoid outdated reference to invoked store instance
+ ApplicationFactory::getInstance()->clear();
+ $maintenance = new $this->maintenanceClass;
+
+ if ( !( $maintenance instanceof \Maintenance ) ) {
+ throw new DomainException( "Expected a Maintenance instance" );
+ }
+
+ // isset/ null
+ if ( isset( $this->options['quiet'] ) && $this->options['quiet'] === false ) {
+ unset( $this->options['quiet'] );
+ }
+
+ $maintenance->loadParamsAndArgs(
+ $this->maintenanceClass,
+ $this->options
+ );
+
+ if ( $this->messageReporter !== null && method_exists( $maintenance, 'setMessageReporter' ) ) {
+ $maintenance->setMessageReporter( $this->messageReporter );
+ }
+
+ ob_start();
+ $result = $maintenance->execute();
+ $this->output = ob_get_contents();
+
+ while ( ob_get_level() > $obLevel ) {
+ ob_end_clean();
+ }
+
+ return $result;
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @return string
+ */
+ public function getOutput() {
+ return $this->output;
+ }
+
+}
+
+// FIXME SemanticGlossary usage
+class_alias( 'SMW\Tests\Utils\Runners\MaintenanceRunner', 'SMW\Tests\Util\MaintenanceRunner' );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/RunnerFactory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/RunnerFactory.php
new file mode 100644
index 00000000..efa8d8ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/RunnerFactory.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace SMW\Tests\Utils\Runners;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class RunnerFactory {
+
+ /**
+ * @var RunnerFactory
+ */
+ private static $instance = null;
+
+ /**
+ * @since 2.1
+ *
+ * @return RunnerFactory
+ */
+ public static function getInstance() {
+
+ if ( self::$instance === null ) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $maintenanceClass
+ *
+ * @return MaintenanceRunner
+ */
+ public function newMaintenanceRunner( $maintenanceClass ) {
+
+ switch ( $maintenanceClass ) {
+ case 'rebuildPropertyStatistics':
+ $maintenanceClass = 'SMW\Maintenance\RebuildPropertyStatistics';
+ break;
+ case 'rebuildData':
+ $maintenanceClass = 'SMW\Maintenance\RebuildData';
+ break;
+ case 'rebuildConceptCache';
+ $maintenanceClass = 'SMW\Maintenance\RebuildConceptCache';
+ break;
+ case 'setupStore';
+ $maintenanceClass = 'SMW\Maintenance\SetupStore';
+ break;
+ }
+
+ return new MaintenanceRunner( $maintenanceClass );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string|null $jobType
+ *
+ * @return JobQueueRunner
+ */
+ public function newJobQueueRunner( $jobType = null ) {
+ return new JobQueueRunner( $jobType );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string|null $source
+ *
+ * @return XmlImportRunner
+ */
+ public function newXmlImportRunner( $source = null ) {
+ return new XmlImportRunner( $source );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/XmlImportRunner.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/XmlImportRunner.php
new file mode 100644
index 00000000..1ea6ba7f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Runners/XmlImportRunner.php
@@ -0,0 +1,172 @@
+<?php
+
+namespace SMW\Tests\Utils\Runners;
+
+use ImportReporter;
+use ImportStreamSource;
+use RequestContext;
+use RuntimeException;
+use SMW\Tests\TestEnvironment;
+use WikiImporter;
+
+/**
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class XmlImportRunner {
+
+ protected $file = null;
+ protected $requestContext = null;
+ protected $exception = false;
+ protected $result = null;
+ protected $verbose = false;
+
+ /**
+ * @var TestEnvironment
+ */
+ private $testEnvironment;
+
+ public function __construct( $file = null ) {
+ $this->file = $file;
+ $this->testEnvironment = new TestEnvironment();
+ }
+
+ /**
+ * @param string $file
+ */
+ public function setFile( $file ) {
+ $this->file = $file;
+ }
+
+ /**
+ * @param boolean $verbose
+ *
+ * @return XmlImportRunner
+ */
+ public function setVerbose( $verbose = true ) {
+ $this->verbose = $verbose;
+ return $this;
+ }
+
+ /**
+ * @param RequestContext $requestContext
+ */
+ public function setRequestContext( RequestContext $requestContext ) {
+ $this->requestContext = $requestContext;
+ }
+
+ /**
+ * @throws RuntimeException
+ * @return boolean
+ */
+ public function run() {
+
+ $this->unregisterUploadsource();
+ $start = microtime( true );
+ $config = null;
+
+ $source = ImportStreamSource::newFromFile(
+ $this->assertThatFileIsReadableOrThrowException( $this->file )
+ );
+
+ if ( !$source->isGood() ) {
+ throw new RuntimeException( 'Import returned with error(s) ' . serialize( $source->errors ) );
+ }
+
+ // WikiImporter::__construct without a Config instance was deprecated in MediaWiki 1.25.
+ if ( class_exists( '\ConfigFactory' ) ) {
+ $config = \ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+ }
+
+ $importer = new WikiImporter( $source->value, $config );
+ $importer->setDebug( $this->verbose );
+
+ $reporter = new ImportReporter(
+ $importer,
+ false,
+ '',
+ false
+ );
+
+ $reporter->setContext( $this->acquireRequestContext() );
+ $reporter->open();
+ $this->exception = false;
+
+ try {
+ $importer->doImport();
+ } catch ( \Exception $e ) {
+ $this->exception = $e;
+ }
+
+ $this->result = $reporter->close();
+ $this->importTime = microtime( true ) - $start;
+
+ $this->testEnvironment->executePendingDeferredUpdates();
+
+ return $this->result->isGood() && !$this->exception;
+ }
+
+ /**
+ * @throws RuntimeException
+ */
+ public function reportFailedImport() {
+
+ $exceptionAsString = '';
+
+ if ( $this->exception ) {
+ $exceptionAsString = $this->exception->getMessage() . '#' . $this->exception->getTraceAsString();
+ }
+
+ throw new RuntimeException(
+ 'Import failed with ' . "\n" .
+ $exceptionAsString . "\n" .
+ $this->result->getWikiText()
+ );
+ }
+
+ /**
+ * @return integer
+ */
+ public function getElapsedImportTimeInSeconds() {
+ return round( $this->importTime, 7 );
+ }
+
+ protected function acquireRequestContext() {
+
+ if ( $this->requestContext === null ) {
+ $this->requestContext = new RequestContext();
+ }
+
+ return $this->requestContext;
+ }
+
+ private function assertThatFileIsReadableOrThrowException( $file ) {
+
+ $file = str_replace( [ '\\', '/' ], DIRECTORY_SEPARATOR, $file );
+
+ if ( is_readable( $file ) ) {
+ return $file;
+ }
+
+ throw new RuntimeException( "Source file {$file} is not accessible" );
+ }
+
+ /**
+ * MW has an implementation issue on how to use stream_wrapper_register
+ * which causes a "Protocol uploadsource:// is already defined" failure when
+ * used multiple times during import
+ *
+ * @see https://gerrit.wikimedia.org/r/#/c/94351/
+ */
+ private function unregisterUploadsource() {
+ if ( in_array( 'uploadsource', stream_get_wrappers() ) ) {
+ stream_wrapper_unregister( 'uploadsource' );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SemanticDataFactory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SemanticDataFactory.php
new file mode 100644
index 00000000..2b7d620b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SemanticDataFactory.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use RuntimeException;
+use SMW\DIWikiPage;
+use SMW\SemanticData;
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class SemanticDataFactory {
+
+ private $subject = null;
+
+ /**
+ * @since 2.0
+ *
+ * @param Title|string $title
+ */
+ public function setTitle( $title ) {
+
+ if ( is_string( $title ) ) {
+ $title = Title::newFromText( $title );
+ }
+
+ if ( $title instanceof Title ) {
+ return $this->setSubject( DIWikiPage::newFromTitle( $title ) );
+ }
+
+ throw new RuntimeException( "Something went wrong" );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param DIWikiPage $subject
+ */
+ public function setSubject( DIWikiPage $subject ) {
+ $this->subject = $subject;
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param string $title
+ *
+ * @return SemanticData
+ * @throws RuntimeException
+ */
+ public function newEmptySemanticData( $title = null ) {
+
+ if ( $title instanceof DIWikiPage ) {
+ $this->setSubject( $title );
+ } elseif ( $title !== null ) {
+ $this->setTitle( $title );
+ }
+
+ if ( $this->subject !== null ) {
+ return new SemanticData( $this->subject );
+ }
+
+ throw new RuntimeException( "Something went wrong" );
+ }
+
+ /**
+ * @since 2.0
+ */
+ public function null() {
+ $this->subject = null;
+ return this;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SpyLogger.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SpyLogger.php
new file mode 100644
index 00000000..bd18da13
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/SpyLogger.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use Psr\Log\AbstractLogger;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class SpyLogger extends AbstractLogger {
+
+ /**
+ * @var array
+ */
+ private $logs = [];
+
+ /**
+ * @since 2.5
+ *
+ * {@inheritDoc}
+ */
+ public function log( $level, $message, array $context = [] ) {
+
+ if ( is_array( $message ) ) {
+ $message = json_encode( $message );
+ }
+
+ $this->logs[] = [ $level, $message, $context ];
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return array
+ */
+ public function getLogs() {
+ return $this->logs;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return string
+ */
+ public function getMessagesAsString() {
+ $message = '';
+
+ foreach ( $this->logs as $log ) {
+ $message .= ' ' . $log[1];
+ }
+
+ return $message;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/StringBuilder.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/StringBuilder.php
new file mode 100644
index 00000000..21a0a087
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/StringBuilder.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ */
+class StringBuilder {
+
+ private $string = '';
+
+ /**
+ * @since 2.0
+ */
+ public function addnewLine() {
+ $this->string = $this->string . "\n";
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public function addString( $string ) {
+ $this->string = $this->string . $string;
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public function getString() {
+ $string = $this->string;
+ $this->string = '';
+ return $string;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/UtilityFactory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/UtilityFactory.php
new file mode 100644
index 00000000..785db5b1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/UtilityFactory.php
@@ -0,0 +1,248 @@
+<?php
+
+namespace SMW\Tests\Utils;
+
+use Onoi\MessageReporter\SpyMessageReporter;
+use SMW\Tests\Utils\File\BulkFileProvider;
+use SMW\Tests\Utils\File\DummyFileCreator;
+use SMW\Tests\Utils\File\JsonFileReader;
+use SMW\Tests\Utils\File\LocalFileUpload;
+use SMW\Tests\Utils\Fixtures\FixturesFactory;
+use SMW\Tests\Utils\Page\PageEditor;
+use SMW\Tests\Utils\Runners\RunnerFactory;
+use SMW\Tests\Utils\Validators\ValidatorFactory;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class UtilityFactory {
+
+ /**
+ * @var UtilityFactory
+ */
+ private static $instance = null;
+
+ /**
+ * @since 2.1
+ *
+ * @return UtilityFactory
+ */
+ public static function getInstance() {
+
+ if ( self::$instance === null ) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return MwApiFactory
+ */
+ public function newMwApiFactory() {
+ return new MwApiFactory();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return ValidatorFactory
+ */
+ public function newValidatorFactory() {
+ return new ValidatorFactory();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return StringBuilder
+ */
+ public function newStringBuilder() {
+ return new StringBuilder();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return MwHooksHandler
+ */
+ public function newMwHooksHandler() {
+ return new MwHooksHandler();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return ParserFactory
+ */
+ public function newParserFactory() {
+ return new ParserFactory();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return FixturesFactory
+ */
+ public function newFixturesFactory() {
+ return new FixturesFactory();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticDataFactory
+ */
+ public function newSemanticDataFactory() {
+ return new SemanticDataFactory();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return RunnerFactory
+ */
+ public function newRunnerFactory() {
+ return new RunnerFactory();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return PageDeleter
+ */
+ public function newPageDeleter() {
+ return new PageDeleter();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return PageRefresher
+ */
+ public function newPageRefresher() {
+ return new PageRefresher();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return PageCreator
+ */
+ public function newPageCreator() {
+ return new PageCreator();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return PageEditor
+ */
+ public function newPageEditor() {
+ return new PageEditor();
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return PageReader
+ */
+ public function newPageReader() {
+ return new PageReader();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $file|null
+ *
+ * @return JsonFileReader
+ */
+ public function newJsonFileReader( $file = null ) {
+ return new JsonFileReader( $file );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $path
+ *
+ * @return BulkFileProvider
+ */
+ public function newBulkFileProvider( $path ) {
+ return new BulkFileProvider( $path );
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param string $localUploadPath
+ * @param $desiredDestName
+ *
+ * @return LocalFileUpload
+ */
+ public function newLocalFileUploadWithCopy( $localUploadPath, $desiredDestName ) {
+
+ // Use to create a copy to avoid having the original file being
+ // deleted after the upload
+ $dummyFileCreator = new DummyFileCreator();
+ $dummyFileCreator->createFileWithCopyFrom( $desiredDestName, $localUploadPath );
+
+ return new LocalFileUpload(
+ $dummyFileCreator->getPath(),
+ $desiredDestName
+ );
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return LocalFileUpload
+ */
+ public function newLocalFileUpload() {
+
+ $localFileUpload = new LocalFileUpload();
+
+ $localFileUpload->setDummyFileCreator(
+ new DummyFileCreator()
+ );
+
+ return $localFileUpload;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param $length
+ * @param $prefix identify a specific random string during testing
+ *
+ * @return string
+ */
+ public function createRandomString( $length = 10, $prefix = null ) {
+ return $prefix . ( $prefix ? '-' : '' ) . substr( str_shuffle( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, $length );
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return SpyLogger
+ */
+ public function newSpyLogger() {
+ return new SpyLogger();
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @return SpyMessageReporter
+ */
+ public function newSpyMessageReporter() {
+ return new SpyMessageReporter();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ExportDataValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ExportDataValidator.php
new file mode 100644
index 00000000..fc89a262
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ExportDataValidator.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use SMWExpData as ExpData;
+use SMWExpResource as ExpResource;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ExportDataValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @since 2.0
+ *
+ * @param mixed $expected
+ * @param ExpData $exportData
+ */
+ public function assertThatExportDataContainsProperty( $expectedProperties, ExpData $exportData ) {
+
+ $expProperties = $exportData->getProperties();
+
+ $this->assertNotEmpty( $expProperties );
+
+ $expectedProperties = is_array( $expectedProperties ) ? $expectedProperties : [ $expectedProperties ];
+ $expectedToCount = count( $expectedProperties );
+ $actualComparedToCount = 0;
+
+ $assertThatExportDataContainsProperty = false;
+
+ foreach ( $expProperties as $expProperty ) {
+ foreach ( $expectedProperties as $expectedProperty ) {
+ if ( $expectedProperty->getHash() === $expProperty->getHash() ) {
+ $actualComparedToCount++;
+ $assertThatExportDataContainsProperty = true;
+ }
+ }
+ }
+
+ $this->assertTrue( $assertThatExportDataContainsProperty );
+
+ $this->assertEquals(
+ $expectedToCount,
+ $actualComparedToCount
+ );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param mixed $expected
+ * @param ExpResource $selectedElement
+ * @param ExpData $exportData
+ */
+ public function assertThatExportDataContainsResource( $expectedResources, ExpResource $selectedElement, ExpData $exportData ) {
+
+ $expElements = $exportData->getValues( $selectedElement );
+
+ $this->assertNotEmpty( $expElements );
+
+ $expectedResources = is_array( $expectedResources ) ? $expectedResources : [ $expectedResources ];
+ $expectedToCount = count( $expectedResources );
+ $actualComparedToCount = 0;
+
+ $assertThatExportDataContainsResource = false;
+
+ foreach ( $expElements as $expElement ) {
+ foreach ( $expectedResources as $expectedResource ) {
+ if ( $expectedResource->getHash() === $expElement->getHash() ) {
+ $actualComparedToCount++;
+ $assertThatExportDataContainsResource = true;
+ }
+ }
+ }
+
+ $this->assertTrue(
+ $assertThatExportDataContainsResource,
+ 'Asserts that a resource is set'
+ );
+
+ $this->assertEquals(
+ $expectedToCount,
+ $actualComparedToCount,
+ 'Asserts that all listed resources are set'
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/HtmlValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/HtmlValidator.php
new file mode 100644
index 00000000..66af8019
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/HtmlValidator.php
@@ -0,0 +1,141 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use DOMDocument;
+use Symfony\Component\CssSelector\CssSelectorConverter;
+
+/**
+ * @license GNU GPL v2+
+ * @since 3.0
+ *
+ * @author Stephan Gambke
+ */
+class HtmlValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @var array
+ */
+ private $documentCache = [];
+
+ /**
+ * @var null|boolean
+ */
+ private $canUse;
+
+ /**
+ * @param string $actual
+ * @param string $message
+ */
+ public function assertThatHtmlIsValid( $actual, $message = '' ) {
+
+ $document = $this->getDomDocumentFromHtmlFragment( $actual );
+
+ self::assertTrue( $document !== false, "Failed test `{$message}` (assertion HtmlIsValid) for $actual" );
+ }
+
+ /**
+ * @return boolean
+ */
+ public function canUse() {
+
+ if ( $this->canUse === null ) {
+ $this->canUse = class_exists( '\Symfony\Component\CssSelector\CssSelectorConverter' );
+ }
+
+ return $this->canUse;
+ }
+
+ /**
+ * @param string $fragment
+ *
+ * @return bool|DOMDocument
+ */
+ private function getDomDocumentFromHtmlFragment( $fragment ) {
+
+ $cacheKey = md5( $fragment );
+
+ if ( !isset( $this->documentCache[ $cacheKey ] ) ) {
+ $this->addHtmlFragmentToCache( $fragment, $cacheKey );
+ }
+
+ return $this->documentCache[ $cacheKey ];
+ }
+
+ /**
+ * @param $fragment
+ * @param $cacheKey
+ */
+ private function addHtmlFragmentToCache( $fragment, $cacheKey ) {
+
+ $fragment = self::wrapHtmlFragment( $fragment );
+
+ $document = new DOMDocument();
+ $document->preserveWhiteSpace = false;
+
+ libxml_use_internal_errors( true );
+ $result = $document->loadHTML( $fragment );
+ libxml_use_internal_errors( false );
+
+ $this->documentCache[ $cacheKey ] = ( $result === true ) ? $document : false;
+
+ }
+
+ /**
+ * @param string $fragment
+ *
+ * @return string
+ */
+ private static function wrapHtmlFragment( $fragment ) {
+ return "<!DOCTYPE html><html><head><meta charset='utf-8'/><title>SomeTitle</title></head><body>$fragment</body></html>";
+ }
+
+ /**
+ * @param string | string[] $cssSelectors
+ * @param string $htmlFragment
+ * @param string $message
+ */
+ public function assertThatHtmlContains( $cssSelectors, $htmlFragment, $message = '', $expected = true ) {
+
+ $document = $this->getDomDocumentFromHtmlFragment( $htmlFragment );
+ $xpath = new \DOMXPath( $document );
+ $converter = new CssSelectorConverter();
+
+ foreach ( $cssSelectors as $selector ) {
+
+ if ( is_array( $selector ) ) {
+ $expectedCount = array_pop( $selector );
+ $expectedCountText = ( ( $expected === true) ? '' : 'not ') . $expectedCount;
+ $selector = array_shift( $selector );
+ } else {
+ $expectedCount = false;
+ $expectedCountText = ( $expected === true) ? 'at least 1' : 'none';
+ }
+
+ $message = "Failed assertion for test case `{$message}` on: \n=====\n$htmlFragment\n=====\nExpected pattern: `$selector`\n";
+
+ try {
+ // Symfony\Component\CssSelector\Exception\SyntaxErrorException: Expected selector ...
+ $entries = $xpath->evaluate( $converter->toXPath( $selector ) );
+ $actualCount = $entries->length;
+
+ $message .= "Expected occurrences: {$expectedCountText}\nFound occurrences: {$actualCount}\n";
+
+ } catch ( \Exception $e ) {
+ $actualCount = 0;
+ $message .= "CssSelector: " . $e->getMessage();
+ }
+
+ self::assertTrue( ( ( $expectedCount === false && $actualCount > 0 ) || ( $actualCount === $expectedCount ) ) === $expected, $message );
+ }
+ }
+
+ /**
+ * @param string | string[] $cssSelectors
+ * @param string $htmlFragment
+ * @param string $message
+ */
+ public function assertThatHtmlNotContains( $cssSelectors, $htmlFragment, $message = '' ) {
+ $this->assertThatHtmlContains( $cssSelectors, $htmlFragment, $message, false );
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/IncomingSemanticDataValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/IncomingSemanticDataValidator.php
new file mode 100644
index 00000000..ed7fc6f5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/IncomingSemanticDataValidator.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use SMW\DIWikiPage;
+use SMW\Store;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class IncomingSemanticDataValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @since 2.5
+ *
+ * @param Store $store
+ */
+ public function __construct( Store $store ) {
+ $this->store = $store;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $incomingSemanticData [description]
+ * @param DIWikiPage $subject
+ * @param string $message
+ */
+ public function assertThatIncomingDataAreSet( array $incomingSemanticData, DIWikiPage $subject, $message ) {
+
+ if ( !isset( $incomingSemanticData['propertyKeys'] ) ) {
+ return;
+ }
+
+ $incomingProperties = $this->store->getInProperties( $subject );
+
+ $this->assertCount(
+ count( $incomingSemanticData['propertyKeys'] ),
+ $incomingProperties,
+ "Failed asserting count for incoming `propertyKeys` on " . $message . '"'
+ );
+
+ $this->doAssertPropertiesAndValues(
+ $incomingSemanticData,
+ $incomingProperties,
+ $subject,
+ $message
+ );
+ }
+
+ private function doAssertPropertiesAndValues( $incomingSemanticData, $incomingProperties, $subject, $message ) {
+
+ $incomingPropertyValues = [];
+
+ foreach ( $incomingProperties as $property ) {
+
+ $key = $property->getKey();
+
+ $this->assertContains(
+ $key,
+ $incomingSemanticData['propertyKeys'],
+ $this->createMessage( 'propertyKeys', $key, $message, $incomingSemanticData['propertyKeys'] )
+ );
+
+ if ( !isset( $incomingSemanticData['propertyValues'] ) ) {
+ continue;
+ }
+
+ $propertySubjects = $this->store->getPropertySubjects( $property, $subject );
+
+ foreach ( $propertySubjects as $propertySubject ) {
+ $incomingPropertyValues[] = $propertySubject->getSerialization();
+ }
+ }
+
+ foreach ( $incomingPropertyValues as $value ) {
+ $this->assertContains(
+ $value,
+ $incomingSemanticData['propertyValues'],
+ $this->createMessage( 'propertyValues', $value, $message, $incomingSemanticData['propertyValues'] )
+ );
+ }
+ }
+
+ private function createMessage( $section, $key, $message, array $data ) {
+ return "Failed asserting that '{$key}' for incoming `$section` on \"" . $message . '" is listed in [ ' . implode( ',', $data ) . ' ]';
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/NumberValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/NumberValidator.php
new file mode 100644
index 00000000..1bd68f3c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/NumberValidator.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use SMW\Query\QueryComparator;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class NumberValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @since 2.5
+ *
+ * @param integer|string $expected
+ * @param integer|string $actual
+ */
+ public function assertThatNumberComparesTo( $expected, $actual, $message = '' ) {
+ return $this->doAssertWith( $expected, $actual, $message );
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param integer|string $expected
+ * @param array $actual
+ */
+ public function assertThatCountComparesTo( $expected, array $actual, $message = '' ) {
+ return $this->doAssertWith( $expected, count( $actual ), $message );
+ }
+
+ private function doAssertWith( $expected, $actual, $message ) {
+
+ $comparator = QueryComparator::getInstance()->extractComparatorFromString( $expected );
+
+ $expected = (int)$expected;
+ $actual = (int)$actual;
+
+ if ( $comparator === SMW_CMP_EQ ) {
+ return self::assertEquals( $expected, $actual, $message );
+ }
+
+ if ( $comparator === SMW_CMP_GRTR ) {
+ return self::assertGreaterThan( $expected, $actual, $message );
+ }
+
+ if ( $comparator === SMW_CMP_GEQ ) {
+ return self::assertGreaterThanOrEqual( $expected, $actual, $message );
+ }
+
+ if ( $comparator === SMW_CMP_LESS ) {
+ return self::assertLessThan( $expected, $actual, $message );
+ }
+
+ if ( $comparator === SMW_CMP_LEQ ) {
+ return self::assertLessThanOrEqual( $expected, $actual, $message );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QueryResultValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QueryResultValidator.php
new file mode 100644
index 00000000..c349943e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QueryResultValidator.php
@@ -0,0 +1,202 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use Closure;
+use RuntimeException;
+use SMW\DIWikiPage;
+use SMWDataItem as DataItem;
+use SMWDataValue as DataValue;
+use SMWQueryResult as QueryResult;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class QueryResultValidator extends \PHPUnit_Framework_Assert {
+
+ private $dataValueValidationMethod = null;
+
+ /**
+ * @since 2.0
+ *
+ * @param mixed $expected
+ * @param QueryResult $queryResult
+ *
+ * @throws RuntimeException
+ */
+ public function assertThatQueryResultContains( $expected, QueryResult $queryResult ) {
+
+ if ( $expected instanceof DataValue ) {
+ return $this->assertThatDataValueIsSet( $expected, $queryResult );
+ }
+
+ if ( $expected instanceof DataItem ) {
+ return $this->assertThatDataItemIsSet( $expected, $queryResult );
+ }
+
+ throw new RuntimeException( "Expected object is unknown or not registered" );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param $expected
+ * @param QueryResult $queryResult
+ * @param string $message
+ */
+ public function assertThatDataValueIsSet( $expected, QueryResult $queryResult, $message = '' ) {
+
+ $expected = is_array( $expected ) ? $expected : [ $expected ];
+
+ if ( $expected === [] ) {
+ return;
+ }
+
+ $errors = $queryResult->getErrors();
+
+ $this->assertEmpty(
+ $errors,
+ "Failed on {$message} with error(s): " . implode( ',', $errors )
+ );
+
+ if ( $this->dataValueValidationMethod === null ) {
+ $this->useWikiValueForDataValueValidation();
+ }
+
+ while ( $resultArray = $queryResult->getNext() ) {
+ foreach ( $resultArray as $result ) {
+ while ( ( $dataValue = $result->getNextDataValue() ) !== false ) {
+ foreach ( $expected as $key => $exp ) {
+ if ( call_user_func_array( $this->dataValueValidationMethod, [ $exp, $dataValue ] ) ) {
+ unset( $expected[$key] );
+ }
+ }
+ }
+ }
+ }
+
+ $this->assertEmpty(
+ $expected,
+ "Failed on on {$message} to match datavalues [ " . implode( ', ', $expected ) . ' ] against the expected results.'
+ );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param mixed $expected
+ * @param QueryResult $queryResult
+ * @param string $message
+ */
+ public function assertThatDataItemIsSet( $expected, QueryResult $queryResult, $message = '' ) {
+
+ $expected = is_array( $expected ) ? $expected : [ $expected ];
+
+ if ( $expected === [] ) {
+ return;
+ }
+
+ $errors = $queryResult->getErrors();
+
+ $this->assertEmpty(
+ $errors,
+ "Failed on {$message} with error(s): " . implode( ',', $errors )
+ );
+
+ while ( $resultArray = $queryResult->getNext() ) {
+ foreach ( $resultArray as $result ) {
+ while ( ( $dataItem = $result->getNextDataItem() ) !== false ) {
+ foreach ( $expected as $key => $exp ) {
+ if ( $exp->equals( $dataItem ) ) {
+ unset( $expected[$key] );
+ }
+ }
+ }
+ }
+ }
+
+ $this->assertEmpty(
+ $expected,
+ "Failed on {$message} to match dataItems [ " . implode( ', ', $expected ) . ' ] against the expected results.'
+ );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param mixed $expectedSubjects
+ * @param QueryResult $queryResult
+ * @param string $message
+ */
+ public function assertThatQueryResultHasSubjects( $expectedSubjects, QueryResult $queryResult, $message = '' ) {
+
+ $expectedSubjects = is_array( $expectedSubjects ) ? $expectedSubjects : [ $expectedSubjects ];
+ $expectedToCount = count( $expectedSubjects );
+ $actualComparedToCount = 0;
+
+ $errors = $queryResult->getErrors();
+
+ $this->assertEmpty(
+ $errors,
+ "Failed on {$message} with error(s): " . implode( ',', $errors )
+ );
+
+ if ( $expectedToCount == 0 ) {
+ return;
+ }
+
+ $resultSubjects = $queryResult->getResults();
+
+ foreach ( $resultSubjects as $rKey => $resultSubject ) {
+ foreach ( $expectedSubjects as $ekey => $expectedSubject ) {
+
+ if ( $expectedSubject instanceof DIWikiPage && $expectedSubject->equals( $resultSubject ) ) {
+ $actualComparedToCount++;
+ unset( $expectedSubjects[$ekey] );
+ unset( $resultSubjects[$rKey] );
+ }
+ }
+ }
+
+ $this->assertEquals(
+ $expectedToCount,
+ $actualComparedToCount,
+ "Failed on {$message} asserting that " . implode( ', ', $expectedSubjects ) . ' is set.'
+ );
+
+ $this->assertEmpty(
+ $resultSubjects,
+ "Failed on {$message} to match results [ " . implode( ', ', $resultSubjects ) . ' ] against the expected subjects.'
+ );
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @param Closure $validationMethod
+ *
+ * @return QueryResultValidator
+ */
+ public function registerCustomMethodForDataValueValidation( Closure $validationMethod ) {
+ $this->dataValueValidationMethod = $validationMethod;
+ return $this;
+ }
+
+ /**
+ * @since 2.0
+ *
+ * @return QueryResultValidator
+ */
+ public function useWikiValueForDataValueValidation() {
+
+ $this->dataValueValidationMethod = function( DataValue $expectedDataValue, DataValue $dataValue ) {
+ return $expectedDataValue->getWikiValue() === $dataValue->getWikiValue();
+ };
+
+ return $this;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QuerySegmentValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QuerySegmentValidator.php
new file mode 100644
index 00000000..4c6bfac4
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/QuerySegmentValidator.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use SMW\SQLStore\QueryEngine\QuerySegment;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class QuerySegmentValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @since 2.1
+ *
+ * @param mixed $expected
+ * @param QuerySegment[] $querySegment
+ */
+ public function assertThatContainerContains( $expected, array $querySegment ) {
+
+ $expected = is_array( $expected ) ? $expected : [ $expected ];
+
+ $this->assertEquals(
+ count( $expected ),
+ count( $querySegment ),
+ $this->formatMessage( 'container count', count( $expected ), count( $querySegment ) )
+ );
+
+ foreach ( $querySegment as $key => $container ) {
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\QueryEngine\QuerySegment',
+ $container
+ );
+
+ $this->assertThatContainerHasProperties( $expected[$key], $container );
+ }
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param mixed $expected
+ * @param QuerySegment $querySegment
+ */
+ public function assertThatContainerHasProperties( $expected, QuerySegment $querySegment ) {
+ $this->assertPublicProperty( $expected, $querySegment, 'type' );
+ $this->assertPublicProperty( $expected, $querySegment, 'joinfield' );
+ $this->assertPublicProperty( $expected, $querySegment, 'jointable' );
+ $this->assertPublicProperty( $expected, $querySegment, 'sortfields' );
+ $this->assertPublicProperty( $expected, $querySegment, 'components' );
+ $this->assertPublicProperty( $expected, $querySegment, 'alias' );
+ $this->assertPublicProperty( $expected, $querySegment, 'where' );
+ $this->assertPublicProperty( $expected, $querySegment, 'from' );
+ $this->assertPublicProperty( $expected, $querySegment, 'queryNumber' );
+ }
+
+ private function assertPublicProperty( $expected, QuerySegment $querySegment, $property ) {
+
+ if ( !isset( $expected->{$property} ) ) {
+ return null;
+ }
+
+ $this->assertTrue(
+ $expected->{$property} == $querySegment->{$property},
+ $this->formatMessage( $property, $expected->{$property}, $querySegment->{$property} )
+ );
+ }
+
+ private function formatMessage( $id, $expected, $actual ) {
+ return "Asserts {$id} to be expected [ " . $this->formatAsString( $expected ) . ' ] vs. actual [ ' . $this->formatAsString( $actual ) .' ]';
+ }
+
+ private function formatAsString( $expected ) {
+ return is_array( $expected ) ? implode( ', ', $expected ) : $expected;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/SemanticDataValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/SemanticDataValidator.php
new file mode 100644
index 00000000..8eec37b2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/SemanticDataValidator.php
@@ -0,0 +1,436 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use RuntimeException;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\SemanticData;
+use SMWDataItem as DataItem;
+
+/**
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class SemanticDataValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @var boolean
+ */
+ private $strictModeForValueMatch = true;
+
+ /**
+ * @param boolean $strictMode
+ */
+ public function setStrictModeForValueMatch( $strictMode ) {
+ $this->strictModeForValueMatch = (bool)$strictMode;
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param SemanticData $semanticData
+ */
+ public function assertThatSemanticDataIsEmpty( SemanticData $semanticData ) {
+ $this->assertTrue(
+ $this->assertThatSemanticDataIsIndeedEmpty( $semanticData ),
+ 'Asserts that the SemanticData container is empty'
+ );
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param SemanticData $semanticData
+ */
+ public function assertThatSemanticDataIsNotEmpty( SemanticData $semanticData ) {
+ $this->assertFalse(
+ $this->assertThatSemanticDataIsIndeedEmpty( $semanticData ),
+ 'Asserts that the SemanticData container is not empty'
+ );
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param array $expected
+ * @param SemanticData $semanticData
+ */
+ public function assertThatCategoriesAreSet( array $expected, SemanticData $semanticData ) {
+
+ $runCategoryInstanceAssert = false;
+
+ foreach ( $semanticData->getProperties() as $property ) {
+
+ if ( $property->getKey() === DIProperty::TYPE_CATEGORY ) {
+ $runCategoryInstanceAssert = true;
+
+ $this->assertThatPropertyValuesAreSet(
+ $expected,
+ $property,
+ $semanticData->getPropertyValues( $property )
+ );
+ }
+
+ if ( $property->getKey() === DIProperty::TYPE_SUBCATEGORY ) {
+ $runCategoryInstanceAssert = true;
+
+ $this->assertThatPropertyValuesAreSet(
+ $expected,
+ $property,
+ $semanticData->getPropertyValues( $property )
+ );
+ }
+
+ }
+
+ // Issue #124 needs to be resolved first
+ // $this->assertTrue( $runCategoryInstanceAssert, __METHOD__ );
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param integer $count
+ * @param SemanticData $semanticData
+ * @param string|null $msg
+ */
+ public function assertThatSemanticDataHasPropertyCountOf( $count, SemanticData $semanticData, $msg = null ) {
+
+ $prop = [];
+
+ foreach ( $semanticData->getProperties() as $property ) {
+ $prop[] = $property->getKey();
+ }
+
+ $msg = $msg === null ? "Failed asserting property count of {$count}" : $msg;
+ $msg .= ' Counted properties include: ' . json_encode( $prop, JSON_PRETTY_PRINT );
+
+ $this->assertCount( $count, $prop, $msg );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param array $expected
+ * @param array $properties
+ */
+ public function assertHasProperties( array $expected, array $properties ) {
+
+ $expected = isset( $expected['properties'] ) ? $expected['properties'] : $expected;
+
+ foreach ( $properties as $property ) {
+
+ foreach ( $expected as $key => $expectedProperty ) {
+ if ( $property->equals( $expectedProperty ) ) {
+ unset( $expected[$key] );
+ }
+ }
+ }
+
+ $this->assertEmpty(
+ $expected,
+ 'Failed asserting that properties array contains [ ' . $this->formatAsString( $expected ) .' ].'
+ );
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param array $expected
+ * @param DIProperty $property
+ */
+ public function assertThatPropertyHasCharacteristicsAs( array $expected, DIProperty $property ) {
+
+ $runAssertThatPropertyHasCharacteristicsAs = false;
+
+ if ( isset( $expected['property'] ) ) {
+ $this->assertPropertyIsSameAs( $expected['property'], $property );
+ $runAssertThatPropertyHasCharacteristicsAs = true;
+ }
+
+ if ( isset( $expected['propertyKey'] ) ) {
+ $this->assertEquals(
+ $expected['propertyKey'],
+ $property->getKey(),
+ __METHOD__ . " asserts property key for {$property->getLabel()}"
+ );
+
+ $runAssertThatPropertyHasCharacteristicsAs = true;
+ }
+
+ if ( isset( $expected['propertyLabel'] ) ) {
+ $this->assertEquals(
+ $expected['propertyLabel'],
+ $property->getLabel(),
+ __METHOD__ . " asserts property label for '{$property->getKey()}'"
+ );
+
+ $runAssertThatPropertyHasCharacteristicsAs = true;
+ }
+
+ if ( isset( $expected['propertyTypeId'] ) ) {
+ $this->assertEquals(
+ $expected['propertyTypeId'],
+ $property->findPropertyTypeID(),
+ __METHOD__ . " asserts property typeId for '{$property->getKey()}'"
+ );
+
+ $runAssertThatPropertyHasCharacteristicsAs = true;
+ }
+
+ $this->assertTrue( $runAssertThatPropertyHasCharacteristicsAs, __METHOD__ );
+
+ }
+
+ /**
+ * Assertion array should follow:
+ * 'propertyCount' => int
+ * 'propertyLabels' => array() or 'propertyKeys' => array()
+ * 'propertyValues' => array()
+ *
+ * @since 1.9.1
+ *
+ * @param array $expected
+ * @param SemanticData $semanticData
+ */
+ public function assertThatPropertiesAreSet( array $expected, SemanticData $semanticData, $message = '' ) {
+
+ $runPropertiesAreSetAssert = false;
+ $properties = $semanticData->getProperties();
+
+ // Deprecated, use strictPropertyValueMatch
+ if ( isset( $expected['strict-mode-valuematch'] ) ) {
+ $this->setStrictModeForValueMatch( $expected['strict-mode-valuematch'] );
+ }
+
+ if ( isset( $expected['strictPropertyValueMatch'] ) ) {
+ $this->setStrictModeForValueMatch( $expected['strictPropertyValueMatch'] );
+ }
+
+ if ( isset( $expected['propertyCount'] ) ) {
+ $this->assertThatSemanticDataHasPropertyCountOf( $expected['propertyCount'], $semanticData, $message );
+ }
+
+ $report = [
+ '@unresolved' => [],
+ '@valueHint' => []
+ ];
+
+ foreach ( $properties as $property ) {
+
+ $this->assertInstanceOf( '\SMW\DIProperty', $property );
+
+ if ( isset( $expected['properties'] ) ) {
+ $this->assertContainsProperty( $expected['properties'], $property );
+ $runPropertiesAreSetAssert = true;
+ }
+
+ if ( isset( $expected['property'] ) ) {
+ $this->assertPropertyIsSameAs( $expected['property'], $property );
+ $runPropertiesAreSetAssert = true;
+ }
+
+ if ( isset( $expected['propertyKeys'] ) ) {
+ $this->assertContainsPropertyKeys( $expected['propertyKeys'], $property, $message );
+ $runPropertiesAreSetAssert = true;
+ }
+
+ if ( isset( $expected['propertyLabels'] ) ) {
+ $this->assertContainsPropertyLabels( $expected['propertyLabels'], $property );
+ $runPropertiesAreSetAssert = true;
+ }
+
+ if ( isset( $expected['propertyValues'] ) ) {
+ $pv = $semanticData->getPropertyValues( $property );
+ $report[$property->getKey()] = $this->formatAsString( $pv );
+
+ $this->assertThatPropertyValuesAreSet(
+ $expected,
+ $property,
+ $pv
+ );
+
+ $runPropertiesAreSetAssert = true;
+ }
+ }
+
+ // Final ceck for values distributed over different properties
+ if ( isset( $expected['propertyValues'] ) && !$this->strictModeForValueMatch ) {
+ $report['@unresolved'] = $expected['propertyValues'];
+ $report['@valueHint'] = $expected['@valueHint'];
+ $this->assertEmpty(
+ $expected['propertyValues'],
+ "Unmatched values in {$message} for:\n" . json_encode( $report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES )
+ );
+ }
+
+ // Issue #124 needs to be resolved first
+ // $this->assertTrue( $runPropertiesAreSetAssert, __METHOD__ );
+
+ return $runPropertiesAreSetAssert;
+ }
+
+ /**
+ * @since 1.9.1
+ *
+ * @param array $expected
+ * @param DIProperty $property,
+ * @param array $dataItems
+ */
+ public function assertThatPropertyValuesAreSet( array &$expected, DIProperty $property, array $dataItems ) {
+
+ $runPropertyValueAssert = false;
+
+ if ( !isset( $expected['@valueHint'] ) ) {
+ $expected['@valueHint'] = [];
+ }
+
+ foreach ( $dataItems as $dataItem ) {
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByItem( $dataItem, $property );
+
+ switch ( $dataValue->getDataItem()->getDIType() ) {
+ case DataItem::TYPE_TIME:
+ $runPropertyValueAssert = $this->assertContainsPropertyValues( $expected, $dataValue, 'getISO8601Date' );
+ break;
+ case DataItem::TYPE_NUMBER:
+ $runPropertyValueAssert = $this->assertContainsPropertyValues( $expected, $dataValue, 'getNumber' );
+ break;
+ case DataItem::TYPE_BOOLEAN:
+ $runPropertyValueAssert = $this->assertContainsPropertyValues( $expected, $dataValue, 'getBoolean' );
+ break;
+ default:
+ $runPropertyValueAssert = $this->assertContainsPropertyValues( $expected, $dataValue, 'getWikiValue' );
+ break;
+ }
+ }
+
+ // Issue #124 needs to be resolved first
+ // $this->assertTrue( $runPropertyValueAssert, __METHOD__ );
+
+ return $runPropertyValueAssert;
+ }
+
+ private function assertThatSemanticDataIsIndeedEmpty( SemanticData $semanticData ) {
+
+ $property = new DIProperty( '_SKEY' );
+
+ foreach( $semanticData->getPropertyValues( $property ) as $dataItem ) {
+ $semanticData->removePropertyObjectValue( $property, $dataItem );
+ }
+
+ return $semanticData->isEmpty();
+ }
+
+ private function assertContainsPropertyKeys( $keys, DIProperty $property, $message = null ) {
+
+ $keys = str_replace( " ", "_", $keys );
+ $message = ( $message === null ? 'Failed asserting' : "Failed asserting \"$message\"" );
+
+ $this->assertContains(
+ $property->getKey(),
+ $keys,
+ "{$message} property key: '{$property->getLabel()}' in ({$this->formatAsString( $keys )})"
+ );
+ }
+
+ private function assertContainsPropertyLabels( $labels, DIProperty $property ) {
+ $this->assertContains(
+ $property->getLabel(),
+ $labels,
+ __METHOD__ . " asserts property label for '{$property->getKey()}' with ({$this->formatAsString( $labels )})"
+ );
+ }
+
+ private function assertContainsProperty( array $properties, DIProperty $property ) {
+
+ $runContainsPropertyAssert = false;
+
+ foreach ( $properties as $expectedproperty ) {
+
+ if ( $property->equals( $expectedproperty ) ) {
+ $runContainsPropertyAssert = true;
+ break;
+ }
+ }
+
+ // Issue #124 needs to be resolved first
+ // $this->assertTrue( $runContainsPropertyAssert, __METHOD__ );
+ }
+
+ private function assertPropertyIsSameAs( DIProperty $expectedproperty, DIProperty $property ) {
+ $this->assertTrue(
+ $property->equals( $expectedproperty ),
+ __METHOD__ . ' asserts that two properties are equal'
+ );
+ }
+
+ private function assertContainsPropertyValues( &$expected, $dataValue, $defaultFormatter, $formatterParameters = [] ) {
+
+ if ( !isset( $expected['propertyValues'] ) ) {
+ throw new RuntimeException( "Expected a 'propertyValues' array index" );
+ }
+
+ $formatter = [ $dataValue, $defaultFormatter ];
+ $valueSerialization = $dataValue->getDataItem()->getSerialization();
+
+ if ( isset( $expected['valueFormatter'] ) && is_callable( $expected['valueFormatter'] ) ) {
+ $formatter = $expected['valueFormatter'];
+ $formatterParameters = [ $dataValue ];
+ }
+
+ $value = call_user_func_array( $formatter, $formatterParameters );
+ $expected['@valueHint'][] = $value;
+
+ if ( $this->strictModeForValueMatch ) {
+
+ $this->assertContains(
+ $value,
+ $expected['propertyValues'],
+ __METHOD__ .
+ " for '{$dataValue->getProperty()->getKey()}'" .
+ " as '{$dataValue->getTypeID()}'" .
+ " with ({$this->formatAsString( $expected['propertyValues'] )})"
+ );
+
+ return true;
+ }
+
+ // Be more lenient towards value comparison by just eliminating a matched pair
+ foreach ( $expected['propertyValues'] as $key => $propertyValue ) {
+
+ if ( is_bool( $value ) && $value === $propertyValue ) {
+ unset( $expected['propertyValues'][$key] );
+ continue;
+ }
+
+ if ( ( is_numeric( $value ) && is_numeric( $propertyValue ) ) && $value == $propertyValue ) {
+ unset( $expected['propertyValues'][$key] );
+ continue;
+ }
+
+ if ( strpos( $propertyValue, (string)$value ) !== false ) {
+ unset( $expected['propertyValues'][$key] );
+ continue;
+ }
+
+ if ( $propertyValue === $valueSerialization ) {
+ unset( $expected['propertyValues'][$key] );
+ }
+ }
+
+ return true;
+ }
+
+ private function formatAsString( $expected ) {
+ return is_array( $expected ) ? implode( ', ', $expected ) : $expected;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/StringValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/StringValidator.php
new file mode 100644
index 00000000..ed128e0f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/StringValidator.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class StringValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @since 2.1
+ *
+ * @param mixed $expected
+ * @param string $actual
+ */
+ public function assertThatStringContains( $expected, $actual, $message = '' ) {
+
+ $callback = function( &$expected, $actual, &$actualCounted ) {
+ foreach ( $expected as $key => $pattern ) {
+ if ( $this->isMatch( $pattern, $actual ) ) {
+ $actualCounted++;
+ unset( $expected[$key] );
+ }
+ }
+ };
+
+ $this->doAssertWith( $expected, $actual, $message, 'StringContains', $callback );
+ }
+
+ /**
+ * @since 2.3
+ *
+ * @param mixed $expected
+ * @param string $actual
+ */
+ public function assertThatStringNotContains( $expected, $actual, $message = '' ) {
+
+ $callback = function( &$expected, $actual, &$actualCounted ) {
+ foreach ( $expected as $key => $pattern ) {
+ if ( $this->isMatch( $pattern, $actual ) === false ) {
+ $actualCounted++;
+ unset( $expected[$key] );
+ }
+ }
+ };
+
+ $this->doAssertWith( $expected, $actual, $message, 'StringNotContains', $callback );
+ }
+
+ private function doAssertWith( $expected, $actual, $message = '', $method = '', $callback ) {
+
+ if ( !is_array( $expected ) ) {
+ $expected = [ $expected ];
+ }
+
+ $expected = array_filter( $expected, 'strlen' );
+
+ if ( $expected === [] ) {
+ return self::assertTrue( true, $message );
+ }
+
+ self::assertInternalType(
+ 'string',
+ $actual
+ );
+
+ $expectedToCount = count( $expected );
+ $actualCounted = 0;
+
+ call_user_func_array(
+ $callback,
+ [ &$expected, $actual, &$actualCounted ]
+ );
+
+ self::assertEquals(
+ $expectedToCount,
+ $actualCounted,
+ "Failed \"{$message}\" for $method:\n==== (actual) ====\n$actual\n==== (expected) ====\n" . $this->toString( $expected )
+ );
+ }
+
+ private function isMatch( $pattern, $source ) {
+
+ // use /.../ indicator to use the preg_match search match
+ if ( strlen( $pattern) >= 2 && substr( $pattern, 0, 1) === '/' && substr( $pattern, -1) === '/' ) {
+
+ return (bool) preg_match( $pattern, $source );
+
+ }
+
+ // use .* indicator to use the wildcard search match
+ if ( strpos( $pattern, '.*' ) !== false ) {
+
+ $pattern = preg_quote( $pattern, '/' );
+ $pattern = str_replace( '\.\*', '.*?', $pattern );
+
+ return (bool) preg_match( '/' . $pattern . '/', $source );
+
+ }
+
+ // use a simple strpos (as it is faster)
+ return strpos( $source, $pattern ) !== false;
+
+ }
+
+ private function toString( $expected ) {
+ return "[ " . ( is_array( $expected ) ? implode( " ], [ ", $expected ) : $expected ) . " ]\n";
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/TitleValidator.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/TitleValidator.php
new file mode 100644
index 00000000..16b70802
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/TitleValidator.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class TitleValidator extends \PHPUnit_Framework_Assert {
+
+ /**
+ * @since 2.1
+ */
+ public function assertThatTitleIsNotKnown( $titles ) {
+ $this->assertTitleExists( false, $titles );
+ }
+
+ /**
+ * @since 2.1
+ */
+ public function assertThatTitleIsKnown( $titles ) {
+ $this->assertTitleExists( true, $titles );
+ }
+
+ private function assertTitleExists( $isExpected, $titles ) {
+
+ if ( !is_array( $titles ) ) {
+ $titles = [ $titles ];
+ }
+
+ foreach ( $titles as $title ) {
+
+ if ( !$title instanceof Title && is_string( $title ) ) {
+ $title = Title::newFromText( $title );
+ }
+
+ $this->assertEquals( $isExpected, $title->exists(), $title->getPrefixedText() );
+ }
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ValidatorFactory.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ValidatorFactory.php
new file mode 100644
index 00000000..223f07ce
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/Validators/ValidatorFactory.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace SMW\Tests\Utils\Validators;
+
+use SMW\Store;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class ValidatorFactory {
+
+ /**
+ * @since 2.1
+ *
+ * @return StringValidator
+ */
+ public function newStringValidator() {
+ return new StringValidator();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return NumberValidator
+ */
+ public function newNumberValidator() {
+ return new NumberValidator();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return SemanticDataValidator
+ */
+ public function newSemanticDataValidator() {
+ return new SemanticDataValidator();
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param Store $store
+ *
+ * @return IncomingSemanticDataValidator
+ */
+ public function newIncomingSemanticDataValidator( Store $store ) {
+ return new IncomingSemanticDataValidator( $store );
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return QueryResultValidator
+ */
+ public function newQueryResultValidator() {
+ return new QueryResultValidator();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return ExportDataValidator
+ */
+ public function newExportDataValidator() {
+ return new ExportDataValidator();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @return TitleValidator
+ */
+ public function newTitleValidator() {
+ return new TitleValidator();
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @return QuerySegmentValidator
+ */
+ public function newQuerySegmentValidator() {
+ return new QuerySegmentValidator();
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @return HtmlValidator
+ */
+ public function newHtmlValidator() {
+ return new HtmlValidator();
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/ContentParserTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/ContentParserTest.php
new file mode 100644
index 00000000..7a0661bf
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/ContentParserTest.php
@@ -0,0 +1,330 @@
+<?php
+
+namespace SMW\Test;
+
+use ContentHandler;
+use Parser;
+use Revision;
+use SMW\ContentParser;
+use SMW\Tests\Utils\Mock\MockTitle;
+use TextContent;
+use TextContentHandler;
+use Title;
+
+/**
+ * @covers \SMW\ContentParser
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ContentParserTest extends SemanticMediaWikiTestCase {
+
+ public function getClass() {
+ return '\SMW\ContentParser';
+ }
+
+ private function newInstance( Title $title = null, $parser = null ) {
+
+ if ( $title === null ) {
+ $title = Title::newFromText( __METHOD__ );
+ }
+
+ return new ContentParser( $title, $parser );
+ }
+
+ public function testCanConstruct() {
+ $this->assertInstanceOf( $this->getClass(), $this->newInstance() );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testCanParseOnInstance() {
+ $this->assertInstanceOf( $this->getClass(), $this->newInstance()->parse() );
+ }
+
+ /**
+ * @depends testCanParseOnInstance
+ */
+ public function testRunParseOnText() {
+
+ $text = 'Foo-1-' . __METHOD__;
+ $expected = '<p>' . $text . "\n" . '</p>';
+
+ $this->assertParserOutput( $expected, $this->newInstance()->parse( $text ) );
+ }
+
+ /**
+ * @dataProvider titleRevisionDataProvider
+ */
+ public function testRunParseOnTitle( $setup, $expected, $withContentHandler = false ) {
+
+ $instance = $this->getMockBuilder( '\SMW\ContentParser' )
+ ->setConstructorArgs( [ $setup['title'], new Parser() ] )
+ ->setMethods( [ 'hasContentHandler' ] )
+ ->getMock();
+
+ $instance->expects( $this->any() )
+ ->method( 'hasContentHandler' )
+ ->will( $this->returnValue( $withContentHandler ) );
+
+ $instance->setRevision( $setup['revision'] );
+
+ $this->assertInstanceAfterParse( $expected, $instance->parse() );
+
+ }
+
+ /**
+ * @dataProvider contentDataProvider
+ *
+ * @since 1.9
+ */
+ public function testRunParseOnTitleWithContentHandler( $setup, $expected ) {
+
+ if ( !class_exists( 'ContentHandler') ) {
+ $this->markTestSkipped(
+ 'Skipping test due to missing class (probably MW 1.21 or lower).'
+ );
+ }
+
+ $this->testRunParseOnTitle( $setup, $expected, true );
+ }
+
+ protected function assertInstanceAfterParse( $expected, $instance ) {
+
+ $this->assertInstanceOf( $this->getClass(), $instance );
+
+ if ( $expected['error'] ) {
+ return $this->assertError( $instance );
+ }
+
+ $this->assertParserOutput( $expected['text'], $instance );
+ }
+
+ protected function assertError( $instance ) {
+ $this->assertInternalType( 'array', $instance->getErrors() );
+ $this->assertNotEmpty( $instance->getErrors() );
+ }
+
+ protected function assertParserOutput( $text, $instance ) {
+
+ $this->assertInstanceOf( 'ParserOutput', $instance->getOutput() );
+
+ if ( $text !== '' ) {
+
+ return $this->assertContains(
+ $text,
+ $instance->getOutput()->getText(),
+ 'Asserts that getText() returns expected text component'
+ );
+
+ }
+
+ $this->assertEmpty( $instance->getOutput()->getText() );
+ }
+
+ /**
+ * @return array
+ */
+ public function titleRevisionDataProvider() {
+
+ $provider = [];
+
+ $text = 'Foo-2-' . __METHOD__;
+ $expected ='<p>' . $text . "\n" . '</p>';
+
+ // #0 Title does not exists
+ $title = $this->newMockBuilder()->newObject( 'Title', [
+ 'getDBkey' => 'Lila',
+ 'exists' => false,
+ 'getText' => null,
+ 'getPageLanguage' => $this->getLanguage()
+ ] );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'revision' => null,
+ ],
+ [
+ 'error' => true,
+ 'text' => ''
+ ]
+ ];
+
+ // #1 Valid revision
+ // Required by MW 1.29, method got removed
+ if ( method_exists( 'Revision', 'getText' ) ) {
+ $title = $this->newMockBuilder()->newObject( 'Title', [
+ 'getDBkey' => 'Lula',
+ 'exists' => true,
+ 'getPageLanguage' => $this->getLanguage()
+ ] );
+
+ $revision = $this->newMockBuilder()->newObject( 'Revision', [
+ 'getId' => 9001,
+ 'getUser' => 'Lala',
+ 'getText' => $text,
+ ] );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'revision' => $revision,
+ ],
+ [
+ 'error' => false,
+ 'text' => $expected
+ ]
+ ];
+ }
+
+ // #2 Null revision
+ $title = $this->newMockBuilder()->newObject( 'Title', [
+ 'getDBkey' => 'Lula',
+ 'exists' => true,
+ 'getPageLanguage' => $this->getLanguage()
+ ] );
+
+ $revision = null;
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'revision' => $revision,
+ ],
+ [
+ 'error' => true,
+ 'text' => ''
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function contentDataProvider() {
+
+ $provider = [];
+
+ if ( !class_exists( 'ContentHandler') ) {
+ $provider[] = [ [], [] ];
+ return $provider;
+ }
+
+ $text = 'Foo-3-' . __METHOD__;
+
+ // #0 Title does not exists
+ $title = MockTitle::buildMock( 'Lila' );
+
+ $title->expects( $this->any() )
+ ->method( 'exists' )
+ ->will( $this->returnValue( false ) );
+
+ $title->expects( $this->any() )
+ ->method( 'getPageLanguage' )
+ ->will( $this->returnValue( $this->getLanguage() ) );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'revision' => null,
+ ],
+ [
+ 'error' => true,
+ 'text' => ''
+ ]
+ ];
+
+ // #1 Valid revision
+ $title = $this->newMockBuilder()->newObject( 'Title', [
+ 'getDBkey' => 'Lula',
+ 'exists' => true,
+ 'getPageLanguage' => $this->getLanguage()
+ ] );
+
+ $revision = $this->newMockBuilder()->newObject( 'Revision', [
+ 'getId' => 9001,
+ 'getUser' => 'Lala',
+ 'getContent' => new TextContent( $text )
+ ] );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'revision' => $revision,
+ ],
+ [
+ 'error' => false,
+ 'text' => $text
+ ]
+ ];
+
+ // #1 Empty content
+ $title = $this->newMockBuilder()->newObject( 'Title', [
+ 'getDBkey' => 'Lula',
+ 'exists' => true,
+ 'getPageLanguage' => $this->getLanguage(),
+ 'getContentModel' => CONTENT_MODEL_WIKITEXT
+ ] );
+
+ $revision = $this->newMockBuilder()->newObject( 'Revision', [
+ 'getId' => 9001,
+ 'getUser' => 'Lala',
+ 'getContent' => false,
+ 'getContentHandler' => new TextContentHandler()
+ ] );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'revision' => $revision,
+ ],
+ [
+ 'error' => false,
+ 'text' => ''
+ ]
+ ];
+
+ // #2 "real" revision and content
+ $title = $this->newTitle();
+ $content = ContentHandler::makeContent( $text, $title, CONTENT_MODEL_WIKITEXT, null );
+
+ $revision = new Revision(
+ [
+ 'id' => 42,
+ 'page' => 23,
+ 'title' => $title,
+
+ 'content' => $content,
+ 'length' => $content->getSize(),
+ 'comment' => "testing",
+ 'minor_edit' => false,
+
+ 'content_format' => null,
+ ]
+ );
+
+ $provider[] = [
+ [
+ 'title' => $title,
+ 'revision' => $revision,
+ ],
+ [
+ 'error' => false,
+ 'text' => $text
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/RecordValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/RecordValueTest.php
new file mode 100644
index 00000000..9635e6e7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/RecordValueTest.php
@@ -0,0 +1,266 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\Tests\TestEnvironment;
+use SMWRecordValue as RecordValue;
+
+/**
+ * @covers \SMWRecordValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class RecordValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWRecordValue',
+ new RecordValue()
+ );
+ }
+
+ public function testGetPropertyDataItems() {
+
+ $expected = [
+ $this->dataItemFactory->newDIProperty( 'Bar' ),
+ $this->dataItemFactory->newDIProperty( 'Foobar' )
+ ];
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getFieldListBy' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar;Foobar' ) ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new RecordValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getPropertyDataItems()
+ );
+
+ $this->assertEquals(
+ $this->dataItemFactory->newDIProperty( 'Foobar' ),
+ $instance->getPropertyDataItemByIndex( 'Foobar' )
+ );
+ }
+
+ public function testParseValue() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getFieldListBy' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar;Foobar' ) ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new RecordValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( '123;abc' );
+ $container = $instance->getDataItem();
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $container
+ );
+
+ $semanticData = $container->getSemanticData();
+
+ $this->assertTrue(
+ $semanticData->hasProperty( $this->dataItemFactory->newDIProperty( 'Foobar' ) )
+ );
+ }
+
+ public function testParseValueOnMissingValues() {
+
+ $instance = new RecordValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( '' );
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $instance->getDataItem()
+ );
+ }
+
+ public function testParseValueWithErroredDv() {
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getRedirectTarget' ] )
+ ->getMockForAbstractClass();
+
+ $this->propertySpecificationLookup->expects( $this->atLeastOnce() )
+ ->method( 'getFieldListBy' )
+ ->will( $this->returnValue( $this->dataItemFactory->newDIBlob( 'Bar;Foobar' ) ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $instance = new RecordValue();
+ $instance->setProperty(
+ $this->dataItemFactory->newDIProperty( 'Foo' )
+ );
+
+ $instance->setUserValue( 'Foo;<>Foo' );
+
+ $this->assertInstanceOf(
+ '\SMWDIError',
+ $instance->getDataItem()
+ );
+
+ $this->assertContains(
+ "smw-datavalue-wikipage-property-invalid-title",
+ implode( ' ', $instance->getErrors() )
+ );
+ }
+
+ public function testGetValuesFromStringWithEncodedSemicolon() {
+
+ $instance = new RecordValue();
+
+ $this->assertEquals(
+ [ 'abc', '1;2', 3 ],
+ $instance->getValuesFromString( 'abc;1\;2;3' )
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testGetQueryDescription( $properties, $value, $expected ) {
+
+ $instance = new RecordValue( '_rec' );
+ $instance->setFieldProperties( $properties );
+
+ $description = $instance->getQueryDescription( htmlspecialchars( $value ) );
+
+ $this->assertEquals(
+ $expected['description'],
+ $description->getQueryString()
+ );
+ }
+
+ /**
+ * @dataProvider valueProvider
+ */
+ public function testGetWikiValue( $properties, $value, $expected ) {
+
+ $instance = new RecordValue( '_rec' );
+ $instance->setFieldProperties( $properties );
+
+ $instance->setUserValue( $value );
+
+ $this->assertEquals(
+ $expected['wikivalue'],
+ $instance->getWikiValue()
+ );
+ }
+
+ public function valueProvider() {
+
+ $dataItemFactory = new DataItemFactory();
+
+ $properties = [
+ $dataItemFactory->newDIProperty( 'Foo' ),
+ $dataItemFactory->newDIProperty( 'Bar' ),
+ 'InvalidFieldPropertyNotSet'
+ ];
+
+ $provider[] = [
+ $properties,
+ "Title without special characters;2001",
+ [
+ 'description' => "[[Foo::Title without special characters]] [[Bar::2001]]",
+ 'wikivalue' => "Title without special characters; 2001"
+ ]
+
+ ];
+
+ $provider[] = [
+ $properties,
+ "Title with $&%'* special characters;(..&^%..)",
+ [
+ 'description' => "[[Foo::Title with $&%'* special characters]] [[Bar::(..&^%..)]]",
+ 'wikivalue' => "Title with $&%'* special characters; (..&^%..)"
+ ]
+ ];
+
+ $provider[] = [
+ $properties,
+ " Title with space before ; After the divider ",
+ [
+ 'description' => "[[Foo::Title with space before]] [[Bar::After the divider]]",
+ 'wikivalue' => "Title with space before; After the divider"
+ ]
+ ];
+
+ $provider[] = [
+ $properties,
+ " Title with backslash\; escape ; After the divider ",
+ [
+ 'description' => "[[Foo::Title with backslash; escape]] [[Bar::After the divider]]",
+ 'wikivalue' => "Title with backslash\; escape; After the divider"
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/UriValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/UriValueTest.php
new file mode 100644
index 00000000..90e12a6d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/UriValueTest.php
@@ -0,0 +1,397 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMWURIValue as UriValue;
+
+/**
+ * @covers \SMWURIValue
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class UriValueTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWURIValue',
+ new UriValue( '_uri' )
+ );
+ }
+
+ /**
+ * @dataProvider uriProvider
+ */
+ public function testUriOutputFormatting( $uri, $caption = false, $linker = null, $expected ) {
+
+ $instance = new UriValue( '_uri' );
+ $instance->setUserValue( $uri, $caption );
+
+ $this->assertOutputFormatting(
+ $instance,
+ $linker,
+ $expected
+ );
+ }
+
+ /**
+ * @dataProvider uriProvider
+ */
+ public function testAnuOutputFormatting( $uri, $caption = false, $linker = null, $expected ) {
+
+ $instance = new UriValue( '_anu' );
+ $instance->setUserValue( $uri, $caption );
+
+ $this->assertOutputFormatting(
+ $instance,
+ $linker,
+ $expected
+ );
+ }
+
+ /**
+ * @dataProvider telProvider
+ */
+ public function testTelOutputFormatting( $uri, $caption = false, $linker = null, $expected ) {
+
+ $instance = new UriValue( '_tel' );
+ $instance->setUserValue( $uri, $caption );
+
+ $this->assertOutputFormatting(
+ $instance,
+ $linker,
+ $expected
+ );
+ }
+
+ /**
+ * @dataProvider emaProvider
+ */
+ public function testEmaOutputFormatting( $uri, $caption = false, $linker = null, $expected ) {
+
+ $instance = new UriValue( '_ema' );
+ $instance->setUserValue( $uri, $caption );
+
+ $this->assertOutputFormatting(
+ $instance,
+ $linker,
+ $expected
+ );
+ }
+
+ private function assertOutputFormatting( $instance, $linker, $expected ) {
+
+ $this->assertEquals(
+ $expected['wikiValue'],
+ $instance->getWikiValue(),
+ 'Failed asserting wikiValue'
+ );
+
+ $this->assertEquals(
+ $expected['longHTMLText'],
+ $instance->getLongHTMLText( $linker ),
+ 'Failed asserting longHTMLText'
+ );
+
+ $this->assertEquals(
+ $expected['longWikiText'],
+ $instance->getLongWikiText( $linker ),
+ 'Failed asserting longWikiText'
+ );
+
+ $this->assertEquals(
+ $expected['shortHTMLText'],
+ $instance->getShortHTMLText( $linker ),
+ 'Failed asserting shortHTMLText'
+ );
+
+ $this->assertEquals(
+ $expected['shortWikiText'],
+ $instance->getShortWikiText( $linker ),
+ 'Failed asserting shortWikiText'
+ );
+ }
+
+ public function uriProvider() {
+
+ $linker = smwfGetLinker();
+
+ // FIXME MW 1.19*
+ $noFollowAttribute = version_compare( $GLOBALS['wgVersion'], '1.20', '<' ) ? '' : ' rel="nofollow"';
+
+ // https://github.com/lanthaler/IRI/blob/master/Test/IriTest.php
+ $provider[] = [
+ 'http://example.org/aaa/bbb#ccc',
+ false,
+ null,
+ [
+ 'wikiValue' => 'http://example.org/aaa/bbb#ccc',
+ 'longHTMLText' => 'http://example.org/aaa/bbb#ccc',
+ 'longWikiText' => 'http://example.org/aaa/bbb#ccc',
+ 'shortHTMLText' => 'http://example.org/aaa/bbb#ccc',
+ 'shortWikiText' => 'http://example.org/aaa/bbb#ccc'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/aaa/bbb#ccc',
+ 'Foo',
+ null,
+ [
+ 'wikiValue' => 'http://example.org/aaa/bbb#ccc',
+ 'longHTMLText' => 'http://example.org/aaa/bbb#ccc',
+ 'longWikiText' => 'http://example.org/aaa/bbb#ccc',
+ 'shortHTMLText' => 'Foo',
+ 'shortWikiText' => 'Foo'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/aaa/bbb#ccc',
+ false,
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/aaa/bbb#ccc',
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">http://example.org/aaa/bbb#ccc</a>',
+ 'longWikiText' => '[http://example.org/aaa/bbb#ccc http://example.org/aaa/bbb#ccc]',
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">http://example.org/aaa/bbb#ccc</a>',
+ 'shortWikiText' => '[http://example.org/aaa/bbb#ccc http://example.org/aaa/bbb#ccc]'
+ ]
+ ];
+
+ #3
+ $provider[] = [
+ 'http://example.org/aaa/bbb#ccc',
+ 'Foo',
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/aaa/bbb#ccc',
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">http://example.org/aaa/bbb#ccc</a>',
+ 'longWikiText' => '[http://example.org/aaa/bbb#ccc http://example.org/aaa/bbb#ccc]',
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">Foo</a>',
+ 'shortWikiText' => '[http://example.org/aaa/bbb#ccc Foo]',
+ ]
+ ];
+
+ #4
+ $provider[] = [
+ 'http://example.org/aaa%2Fbbb#ccc',
+ false,
+ null,
+ [
+ 'wikiValue' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'longHTMLText' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'longWikiText' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'shortHTMLText' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'shortWikiText' => 'http://example.org/aaa%2Fbbb#ccc'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/aaa%2Fbbb#ccc',
+ 'Foo',
+ null,
+ [
+ 'wikiValue' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'longHTMLText' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'longWikiText' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'shortHTMLText' => 'Foo',
+ 'shortWikiText' => 'Foo'
+ ]
+ ];
+
+ #6
+ $provider[] = [
+ 'http://example.org/aaa%2Fbbb#ccc',
+ false,
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">http://example.org/aaa%2Fbbb#ccc</a>',
+ 'longWikiText' => '[http://example.org/aaa/bbb#ccc http://example.org/aaa%2Fbbb#ccc]',
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">http://example.org/aaa%2Fbbb#ccc</a>',
+ 'shortWikiText' => '[http://example.org/aaa/bbb#ccc http://example.org/aaa%2Fbbb#ccc]'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/aaa%2Fbbb#ccc',
+ 'Foo',
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/aaa%2Fbbb#ccc',
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">http://example.org/aaa%2Fbbb#ccc</a>',
+ 'longWikiText' => '[http://example.org/aaa/bbb#ccc http://example.org/aaa%2Fbbb#ccc]',
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/aaa/bbb#ccc">Foo</a>',
+ 'shortWikiText' => '[http://example.org/aaa/bbb#ccc Foo]',
+ ]
+ ];
+
+ #8 UTF-8 encoded string
+ $provider[] = [
+ 'http://example.org/よã†ã“ã--23-7B-7D',
+ false,
+ null,
+ [
+ 'wikiValue' => 'http://example.org/よã†ã“ã--23-7B-7D',
+ 'longHTMLText' => 'http://example.org/よã†ã“ã--23-7B-7D',
+ 'longWikiText' => 'http://example.org/よã†ã“ã--23-7B-7D',
+ 'shortHTMLText' => 'http://example.org/よã†ã“ã--23-7B-7D',
+ 'shortWikiText' => 'http://example.org/よã†ã“ã--23-7B-7D'
+ ]
+ ];
+
+ #9
+ $provider[] = [
+ 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ false,
+ null,
+ [
+ 'wikiValue' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'longHTMLText' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'longWikiText' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'shortHTMLText' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'shortWikiText' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ '一二三',
+ null,
+ [
+ 'wikiValue' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'longHTMLText' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'longWikiText' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'shortHTMLText' => '一二三',
+ 'shortWikiText' => '一二三'
+ ]
+ ];
+
+ # 11
+ $provider[] = [
+ 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ false,
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D">http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D</a>',
+ 'longWikiText' => '[http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D]',
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D">http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D</a>',
+ 'shortWikiText' => '[http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D]'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ '一二三',
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D',
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D">http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D</a>',
+ 'longWikiText' => '[http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D]',
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D">一二三</a>',
+ 'shortWikiText' => '[http://example.org/%E3%82%88%E3%81%86%E3%81%93%E3%81%9D-23-7B-7D 一二三]',
+ ]
+ ];
+
+ # 13
+ $provider[] = [
+ 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ false,
+ null,
+ [
+ 'wikiValue' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ 'longHTMLText' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ 'longWikiText' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ 'shortHTMLText' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ 'shortWikiText' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ '&!_:;@*#Foo',
+ null,
+ [
+ 'wikiValue' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ 'longHTMLText' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ 'longWikiText' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ 'shortHTMLText' => '&!_:;@*#Foo',
+ 'shortWikiText' => '&!_:;@*#Foo'
+ ]
+ ];
+
+ #15
+ $provider[] = [
+ 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ false,
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar', // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.Files.LineLength
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/api?query=%21_:%3B@%2A_#Foo&amp;=_-3DBar">http://example.org/api?query=! :;@* #Foo&amp;=%20-3DBar</a>', // @codingStandardsIgnoreEnd
+ 'longWikiText' => '[http://example.org/api?query=%21_:%3B@%2A_#Foo&=_-3DBar http://example.org/api?query=! :;@* #Foo&=%20-3DBar]', // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.Files.LineLength
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/api?query=%21_:%3B@%2A_#Foo&amp;=_-3DBar">http://example.org/api?query=! :;@* #Foo&amp;=%20-3DBar</a>', // @codingStandardsIgnoreEnd
+ 'shortWikiText' => '[http://example.org/api?query=%21_:%3B@%2A_#Foo&=_-3DBar http://example.org/api?query=! :;@* #Foo&=%20-3DBar]'
+ ]
+ ];
+
+ $provider[] = [
+ 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar',
+ '&!_:;@* #Foo',
+ $linker,
+ [
+ 'wikiValue' => 'http://example.org/api?query=!_:;@* #Foo&=%20-3DBar', // @codingStandardsIgnoreStart phpcs, ignore --sniffs=Generic.Files.LineLength
+ 'longHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/api?query=%21_:%3B@%2A_#Foo&amp;=_-3DBar">http://example.org/api?query=! :;@* #Foo&amp;=%20-3DBar</a>', // @codingStandardsIgnoreEnd
+ 'longWikiText' => '[http://example.org/api?query=%21_:%3B@%2A_#Foo&=_-3DBar http://example.org/api?query=! :;@* #Foo&=%20-3DBar]',
+ 'shortHTMLText' => '<a class="external"' . $noFollowAttribute . ' href="http://example.org/api?query=%21_:%3B@%2A_#Foo&amp;=_-3DBar">&amp;! :;@* #Foo</a>',
+ 'shortWikiText' => '[http://example.org/api?query=%21_:%3B@%2A_#Foo&=_-3DBar &! :;@* #Foo]'
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function telProvider() {
+
+ $provider[] = [
+ '+1-201-555-0123',
+ false,
+ null,
+ [
+ 'wikiValue' => '+1-201-555-0123',
+ 'longHTMLText' => '+1-201-555-0123',
+ 'longWikiText' => '+1-201-555-0123',
+ 'shortHTMLText' => '+1-201-555-0123',
+ 'shortWikiText' => '+1-201-555-0123'
+ ]
+ ];
+
+ return $provider;
+ }
+
+ public function emaProvider() {
+
+ $provider[] = [
+ 'foo@example.org',
+ false,
+ null,
+ [
+ 'wikiValue' => 'foo@example.org',
+ 'longHTMLText' => 'foo@example.org',
+ 'longWikiText' => 'foo@example.org',
+ 'shortHTMLText' => 'foo@example.org',
+ 'shortWikiText' => 'foo@example.org'
+ ]
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/WikiPageValueTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/WikiPageValueTest.php
new file mode 100644
index 00000000..953c2a23
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/DataValues/WikiPageValueTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests\DataValues;
+
+use SMW\DataItemFactory;
+use SMW\Tests\TestEnvironment;
+use SMWWikiPageValue as WikiPageValue;
+
+/**
+ * @covers \SMWWikiPageValue
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 3.1
+ *
+ * @author mwjames
+ */
+class WikiPageValueTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->dataItemFactory = new DataItemFactory();
+
+ $this->propertySpecificationLookup = $this->getMockBuilder( '\SMW\PropertySpecificationLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'PropertySpecificationLookup', $this->propertySpecificationLookup );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ WikiPageValue::class,
+ new WikiPageValue( '' )
+ );
+ }
+
+ public function testDisableInfolinksOnSpecialUsernamePrefix() {
+
+ $instance = new WikiPageValue( '_wpg' );
+
+ $this->assertFalse(
+ $instance->getOption( WikiPageValue::OPT_DISABLE_INFOLINKS )
+ );
+
+ $instance->setDataItem(
+ $this->dataItemFactory->newDIWikiPage( '>Foo', NS_USER )
+ );
+
+ $instance->getTitle();
+
+ $this->assertTrue(
+ $instance->getOption( WikiPageValue::OPT_DISABLE_INFOLINKS )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/HighlighterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/HighlighterTest.php
new file mode 100644
index 00000000..4bc78070
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/HighlighterTest.php
@@ -0,0 +1,117 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\Highlighter;
+
+/**
+ * @covers \SMW\Highlighter
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class HighlighterTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider getTypeDataProvider
+ */
+ public function testCanConstruct( $type ) {
+
+ $this->assertInstanceOf(
+ '\SMW\Highlighter',
+ Highlighter::factory( $type )
+ );
+ }
+
+ /**
+ * @dataProvider getTypeDataProvider
+ */
+ public function testGetTypeId( $type, $expected ) {
+ $results = Highlighter::getTypeId( $type );
+
+ $this->assertInternalType(
+ 'integer',
+ $results
+ );
+
+ $this->assertEquals(
+ $expected,
+ $results
+ );
+ }
+
+ public function testDecode() {
+
+ $this->assertEquals(
+ '&<> ',
+ Highlighter::decode( '&amp;&lt;&gt;&#160;<nowiki></nowiki>' )
+ );
+ }
+
+ /**
+ * @dataProvider getTypeDataProvider
+ */
+ public function testGetHtml( $type ) {
+
+ $instance = Highlighter::factory( $type );
+
+ $instance->setContent( [
+ 'title' => 'Foo'
+ ] );
+
+ // Check without caption/content set
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+
+ $instance->setContent( [
+ 'caption' => '123',
+ 'content' => 'ABC',
+ ] );
+
+ // Check with caption/content set
+ $this->assertInternalType(
+ 'string',
+ $instance->getHtml()
+ );
+ }
+
+ public function testHasHighlighterClass() {
+
+ $instance = Highlighter::factory(
+ Highlighter::TYPE_WARNING
+ );
+
+ $instance->setContent( [
+ 'title' => 'Foo'
+ ] );
+
+ $this->assertTrue(
+ Highlighter::hasHighlighterClass( $instance->getHtml(), 'warning' )
+ );
+ }
+
+ public function getTypeDataProvider() {
+ return [
+ [ '' , Highlighter::TYPE_NOTYPE ],
+ [ 'property', Highlighter::TYPE_PROPERTY ],
+ [ 'text', Highlighter::TYPE_TEXT ],
+ [ 'info', Highlighter::TYPE_INFO ],
+ [ 'help', Highlighter::TYPE_HELP ],
+ [ 'service', Highlighter::TYPE_SERVICE ],
+ [ 'quantity', Highlighter::TYPE_QUANTITY ],
+ [ 'note', Highlighter::TYPE_NOTE ],
+ [ 'warning', Highlighter::TYPE_WARNING ],
+ [ 'error', Highlighter::TYPE_ERROR ],
+ [ 'PrOpErTy', Highlighter::TYPE_PROPERTY ],
+ [ 'ãƒã‚«ãªãƒ†ã‚¹ãƒˆ', Highlighter::TYPE_NOTYPE ],
+ [ '<span>Something that should not work</span>', Highlighter::TYPE_NOTYPE ],
+ [ Highlighter::TYPE_PROPERTY, Highlighter::TYPE_NOTYPE ]
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/InfolinkTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/InfolinkTest.php
new file mode 100644
index 00000000..6a47317a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/InfolinkTest.php
@@ -0,0 +1,243 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\Tests\TestEnvironment;
+use SMWInfolink as Infolink;
+
+/**
+ * @covers \SMWInfolink
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class InfolinkTest extends \PHPUnit_Framework_TestCase {
+
+ private $testEnvironment;
+
+ protected function setUp() {
+
+ $this->testEnvironment = new TestEnvironment(
+ [
+ 'wgContLang' => \Language::factory( 'en' )
+ ]
+ );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testEncodeParameters_ForTitle( array $params, array $expected ) {
+
+ $encodeResult = Infolink::encodeParameters( $params, true );
+
+ $this->assertEquals(
+ $expected[0],
+ $encodeResult
+ );
+ }
+
+ /**
+ * @dataProvider parameterDataProvider
+ */
+ public function testEncodeParameters_NotForTitle( array $params, array $expected ) {
+
+ $encodeResult = Infolink::encodeParameters( $params, false );
+
+ $this->assertEquals(
+ $expected[1],
+ $encodeResult
+ );
+ }
+
+ public function testNewPropertySearchLink_GetText() {
+
+ $instance = Infolink::newPropertySearchLink( 'Foo', 'Bar', 'Foobar' );
+
+ $instance->setCompactLink( false );
+
+ $this->assertContains(
+ 'title=Special:SearchByProperty&x=%3ABar%2FFoobar',
+ $instance->getText( SMW_OUTPUT_RAW )
+ );
+
+ $instance->setCompactLink( true );
+
+ $this->assertContains(
+ 'title=Special:SearchByProperty&cl=OkJhci9Gb29iYXI',
+ $instance->getText( SMW_OUTPUT_RAW )
+ );
+
+ $this->assertEquals(
+ $instance->getURL(),
+ $instance->getText( SMW_OUTPUT_RAW )
+ );
+ }
+
+ public function testGetURL() {
+
+ $instance = new Infolink( true, 'Foo', 'Bar/Foobar' );
+
+ $instance->setCompactLink( true );
+
+ $this->assertContains(
+ '/Bar/Foobar',
+ $instance->getLocalURL()
+ );
+
+ $this->assertContains(
+ '/Bar/Foobar',
+ $instance->getURL()
+ );
+
+ $instance->setParameter( 123, 'foo' );
+
+ $this->assertContains(
+ 'title=Bar/Foobar&cl=Zm9vPTEyMw',
+ $instance->getLocalURL()
+ );
+
+ $this->assertContains(
+ 'title=Bar/Foobar&cl=Zm9vPTEyMw',
+ $instance->getURL()
+ );
+
+ $instance->setCompactLink( false );
+
+ $this->assertContains(
+ 'title=Bar/Foobar&foo=123',
+ $instance->getLocalURL()
+ );
+
+ $this->assertContains(
+ 'title=Bar/Foobar&foo=123',
+ $instance->getURL()
+ );
+ }
+
+ /**
+ * @dataProvider base64Provider
+ */
+ public function testEncodeBase64( $source, $target ) {
+
+ $this->assertContains(
+ $target,
+ Infolink::encodeCompactLink( $source )
+ );
+ }
+
+ /**
+ * @dataProvider base64Provider
+ */
+ public function testEncodeDecodeBase64RoundTrip( $source, $target ) {
+
+ $this->assertEquals(
+ $source,
+ Infolink::decodeCompactLink( Infolink::encodeCompactLink( $source ) )
+ );
+ }
+
+ /**
+ * @dataProvider base64DecodeProvider
+ */
+ public function testDecodeBase64( $source, $target ) {
+
+ $this->assertEquals(
+ $source,
+ Infolink::decodeCompactLink( $target )
+ );
+ }
+
+ public function testNotDecodable() {
+
+ $this->assertNotContains(
+ '%3ABar/Foobar',
+ Infolink::decodeCompactLink( 'eD0lM0FCYXIlMkZGb29iYXI' )
+ );
+ }
+
+ public function base64Provider() {
+
+ yield [
+ '%3ABar/Foobar',
+ 'cl:JTNBQmFyL0Zvb2Jhcg'
+ ];
+
+ yield [
+ '-5B-5BProperty%3A%2B-5D-5D-20-5B-5BCategory%3ALorem-20ipsum-5D-5D/-3FHas-20description%3DDescription/-3FHas-20type/mainlabel=/format=table/class=datatable/sort=/order=asc/offset=100/limit=50',
+ 'cl:YzpFijEOgzAMRU_DGCUFMXooRVUHhl7BgKkiJTiy3YHbF8qA9Jf33ndt59ruLVxIbKuae1Xvoj9WB_ePDzT6sBxxYKG8h1j0m8-bd83zhbrLmXSSWCzyWjV9f9F1sa2QzxjXhCMl8AtLRgPDMZGfEqrCjIYnK4uBZ5lJAHXyvCxKBrcQfIo5GrThBw'
+ ];
+ }
+
+ public function base64DecodeProvider() {
+
+ yield [
+ '%3ABar/Foobar',
+ 'cl:JTNBQmFyL0Zvb2Jhcg'
+ ];
+
+ yield [
+ '%3ABar/Foobar',
+ '%3ABar/Foobar'
+ ];
+
+ yield [
+ '-5B-5BProperty%3A%2B-5D-5D-20-5B-5BCategory%3ALorem-20ipsum-5D-5D/-3FHas-20description%3DDescription/-3FHas-20type/mainlabel=/format=table/class=datatable/sort=/order=asc/offset=100/limit=50',
+ 'cl:YzpNijEOgzAMRU-TbJVSEKOHtgh16NArGDBVpARHtiuV2zeIBekv773_g0t3r3sLFxLbXHtzTRX9viYc8YFGH5Y9vlgo1xCLfvNxc81waYcnatUz6SSxWOTVtX1_otPJtkI-Y1wTjpTALywZDQzHRH5KqAozGh6sLAaeZSYB1MnzsigZXEPwKeZo0IU'
+ ];
+
+ yield [
+ '-5B-5BProperty%3A%2B-5D-5D-20-5B-5BCategory%3ALorem-20ipsum-5D-5D/-3FHas-20description%3DDescription/-3FHas-20type/mainlabel=/format=table/class=datatable/sort=/order=asc/offset=100/limit=50',
+ 'cl:YzpFijEOgzAMRU_DGCUFMXooRVUHhl7BgKkiJTiy3YHbF8qA9Jf33ndt59ruLVxIbKuae1Xvoj9WB_ePDzT6sBxxYKG8h1j0m8-bd83zhbrLmXSSWCzyWjV9f9F1sa2QzxjXhCMl8AtLRgPDMZGfEqrCjIYnK4uBZ5lJAHXyvCxKBrcQfIo5GrThBw'
+ ];
+ }
+
+ public function parameterDataProvider() {
+ return [
+ [
+ // #0
+ [
+ 'format=template',
+ 'link=none'
+ ],
+ [
+ 'format=template/link=none',
+ 'x=format%3Dtemplate%2Flink%3Dnone'
+ ]
+ ],
+
+ // #1 Bug 47010 (space encoding, named args => named%20args)
+ [
+ [
+ 'format=template',
+ 'link=none',
+ 'named args=1'
+ ],
+ [
+ 'format=template/link=none/named-20args=1',
+ 'x=format%3Dtemplate%2Flink%3Dnone%2Fnamed-20args%3D1'
+ ]
+ ],
+
+ // #2 "\"
+ [
+ [
+ "format=foo\bar",
+ ],
+ [
+ 'format=foo-5Cbar',
+ 'x=format%3Dfoo-5Cbar'
+ ]
+ ],
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryPrinterFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryPrinterFactoryTest.php
new file mode 100644
index 00000000..ea3d0609
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryPrinterFactoryTest.php
@@ -0,0 +1,199 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\QueryPrinterFactory;
+use SMW\QueryResultPrinter;
+use SMW\TableResultPrinter;
+use SMWListResultPrinter;
+
+/**
+ * @covers \SMW\QueryPrinterFactory
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class QueryPrinterFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testSingleton() {
+ $instance = QueryPrinterFactory::singleton();
+
+ $this->assertInstanceOf( QueryPrinterFactory::class, $instance );
+ $this->assertTrue( QueryPrinterFactory::singleton() === $instance );
+
+ global $smwgResultFormats, $smwgResultAliases;
+
+ foreach ( $smwgResultFormats as $formatName => $printerClass ) {
+ $this->assertTrue( $instance->hasFormat( $formatName ) );
+ $this->assertInstanceOf( $printerClass, $instance->getPrinter( $formatName ) );
+ }
+
+ foreach ( $smwgResultAliases as $formatName => $aliases ) {
+ $printerClass = $smwgResultFormats[$formatName];
+
+ foreach ( $aliases as $alias ) {
+ $this->assertTrue( $instance->hasFormat( $alias ) );
+ $this->assertInstanceOf( $printerClass, $instance->getPrinter( $formatName ) );
+ }
+ }
+ }
+
+ public function testRegisterFormat() {
+ $factory = new QueryPrinterFactory();
+
+ $factory->registerFormat( 'table', TableResultPrinter::class );
+ $factory->registerFormat( 'list', SMWListResultPrinter::class );
+
+ $this->assertContains( 'table', $factory->getFormats() );
+ $this->assertContains( 'list', $factory->getFormats() );
+ $this->assertCount( 2, $factory->getFormats() );
+
+ $factory->registerFormat( 'table', SMWListResultPrinter::class );
+
+ $printer = $factory->getPrinter( 'table' );
+
+ $this->assertInstanceOf( SMWListResultPrinter::class, $printer );
+ }
+
+ public function testRegisterAliases() {
+ $factory = new QueryPrinterFactory();
+
+ $this->assertEquals( 'foo', $factory->getCanonicalName( 'foo' ) );
+
+ $factory->registerAliases( 'foo', [] );
+ $factory->registerAliases( 'foo', [ 'bar' ] );
+ $factory->registerAliases( 'foo', [ 'baz' ] );
+ $factory->registerAliases( 'ohi', [ 'there', 'o_O' ] );
+
+ $this->assertEquals( 'foo', $factory->getCanonicalName( 'foo' ) );
+
+ $this->assertEquals( 'foo', $factory->getCanonicalName( 'bar' ) );
+ $this->assertEquals( 'foo', $factory->getCanonicalName( 'baz' ) );
+
+ $this->assertEquals( 'ohi', $factory->getCanonicalName( 'there' ) );
+ $this->assertEquals( 'ohi', $factory->getCanonicalName( 'o_O' ) );
+
+ $factory->registerAliases( 'foo', [ 'o_O' ] );
+
+ $this->assertEquals( 'foo', $factory->getCanonicalName( 'o_O' ) );
+ }
+
+ public function testGetPrinter() {
+ $factory = QueryPrinterFactory::singleton();
+
+ foreach ( $factory->getFormats() as $format ) {
+ $printer = $factory->getPrinter( $format );
+ $this->assertInstanceOf( QueryResultPrinter::class, $printer );
+ }
+
+ // In case there are no formats PHPUnit would otherwise complain here.
+ $this->assertTrue( true );
+ }
+
+ public function testGetFormats() {
+ $factory = new QueryPrinterFactory();
+
+ $this->assertInternalType( 'array', $factory->getFormats() );
+
+ $factory->registerFormat( 'table', TableResultPrinter::class );
+ $factory->registerFormat( 'list', SMWListResultPrinter::class );
+
+ $factory->registerAliases( 'foo', [ 'bar' ] );
+ $factory->registerAliases( 'foo', [ 'baz' ] );
+ $factory->registerAliases( 'ohi', [ 'there', 'o_O' ] );
+
+ $formats = $factory->getFormats();
+ $this->assertInternalType( 'array', $formats );
+
+ $this->assertContains( 'table', $factory->getFormats() );
+ $this->assertContains( 'list', $factory->getFormats() );
+ $this->assertCount( 2, $factory->getFormats() );
+ }
+
+ public function testHasFormat() {
+ $factory = new QueryPrinterFactory();
+
+ $this->assertFalse( $factory->hasFormat( 'ohi' ) );
+
+ $factory->registerFormat( 'ohi', 'SMWTablePrinter' );
+ $factory->registerAliases( 'ohi', [ 'there', 'o_O' ] );
+
+ $this->assertTrue( $factory->hasFormat( 'ohi' ) );
+ $this->assertTrue( $factory->hasFormat( 'there' ) );
+ $this->assertTrue( $factory->hasFormat( 'o_O' ) );
+
+ $factory = QueryPrinterFactory::singleton();
+
+ foreach ( $factory->getFormats() as $format ) {
+ $this->assertTrue( $factory->hasFormat( $format ) );
+ }
+ }
+
+ public function testGetPrinterThrowsException() {
+
+ $factory = new QueryPrinterFactory();
+
+ $this->setExpectedException( '\SMW\Query\Exception\ResultFormatNotFoundException' );
+ $factory->getPrinter( 'lula' );
+ }
+
+ public function testGetCanonicalNameThrowsException() {
+
+ $factory = new QueryPrinterFactory();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $factory->getCanonicalName( 9001 );
+ }
+
+ /**
+ * @dataProvider registerFormatExceptioProvider
+ */
+ public function testRegisterFormatThrowsException( $formatName, $class ) {
+
+ $factory = new QueryPrinterFactory();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $factory->registerFormat( $formatName, $class );
+ }
+
+ /**
+ * Register format exception data provider
+ *
+ * @return array
+ */
+ public function registerFormatExceptioProvider() {
+ return [
+ [ 1001, 'Foo' ],
+ [ 'Foo', 9001 ],
+ ];
+ }
+
+ /**
+ * @dataProvider registerAliasesExceptionProvider
+ */
+ public function testRegisterAliasesThrowsException( $formatName, array $aliases ) {
+
+ $factory = new QueryPrinterFactory();
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $factory->registerAliases( $formatName, $aliases );
+ }
+
+ /**
+ * Register aliases exception data provider
+ *
+ * @return array
+ */
+ public function registerAliasesExceptionProvider() {
+ return [
+ [ 1001, [ 'Foo' => 'Bar' ] ],
+ [ 'Foo', [ 'Foo' => 9001 ] ],
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryProcessorTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryProcessorTest.php
new file mode 100644
index 00000000..06280a2d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/QueryProcessorTest.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * @file
+ * @since 1.8
+ */
+
+namespace SMW\Test;
+
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMWQueryProcessor;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * Tests for the SMWQueryProcessor class.
+ *
+ * @since 1.8
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group SMWQueries
+ * @group SMWQueryProcessorTest
+ *
+ * @author Nischay Nahata
+ */
+class SMWQueryProcessorTest extends MwDBaseUnitTestCase {
+
+ use PHPUnitCompat;
+
+ public function createQueryDataProvider() {
+ return [
+ [ '[[Modification date::+]]|?Modification date|sort=Modification date|order=desc' ],
+ ];
+ }
+
+ /**
+ * @dataProvider resultAliasDataProvider
+ */
+ public function testGetResultPrinter_MatchAlias( $alias ) {
+
+ $this->assertInstanceOf(
+ '\SMW\Query\ResultPrinter',
+ SMWQueryProcessor::getResultPrinter( $alias )
+ );
+ }
+
+ public function resultAliasDataProvider() {
+
+ foreach ( $GLOBALS['smwgResultAliases'] as $format => $aliases ) {
+ foreach ( $aliases as $alias ) {
+ yield [ $alias ];
+ }
+ }
+ }
+
+ public function testGetResultPrinter_ThrowsException() {
+
+ $this->setExpectedException( '\SMW\Query\Exception\ResultFormatNotFoundException' );
+ SMWQueryProcessor::getResultPrinter( 'unknown_format' );
+ }
+
+
+ /**
+ * @dataProvider createQueryDataProvider
+ */
+ public function testCreateQuery( $query ) {
+ // TODO: this prevents doing [[Category:Foo||bar||baz]], must document.
+ $rawParams = explode( '|', $query );
+
+ list( $queryString, $parameters, $printouts ) = SMWQueryProcessor::getComponentsFromFunctionParams( $rawParams, false );
+
+ SMWQueryProcessor::addThisPrintout( $printouts, $parameters );
+
+ $parameters = SMWQueryProcessor::getProcessedParams( $parameters, $printouts );
+
+ $this->assertInstanceOf(
+ '\SMWQuery',
+ SMWQueryProcessor::createQuery(
+ $queryString,
+ $parameters,
+ SMWQueryProcessor::SPECIAL_PAGE,
+ '',
+ $printouts
+ ),
+ "Result should be instance of SMWQuery."
+ );
+ }
+
+ /**
+ * @dataProvider rawParamsProvider
+ */
+ public function testQuerStringFromRawParameters( $rawParams, $expected ) {
+
+ list( $queryString, $parameters, $printouts ) = SMWQueryProcessor::getComponentsFromFunctionParams( $rawParams, false );
+
+ $this->assertEquals(
+ $expected,
+ $queryString
+ );
+ }
+
+ public function rawParamsProvider() {
+
+ $provider[] = [
+ [ 'Foo', 'bar' ],
+ 'Foobar'
+ ];
+
+ $provider[] = [
+ [ 'Foo=', 'Bar' ],
+ 'Bar'
+ ];
+
+ $provider[] = [
+ [ '[[Foo::Foo=Bar]]', '+Foo' ],
+ '[[Foo::Foo=Bar]]'
+ ];
+
+ $provider[] = [
+ [ '[[Modification date::+]]', '?Modification date=Date', 'limit=1' ],
+ '[[Modification date::+]]'
+ ];
+
+ $provider[] = [
+ [ '?Foo', 'limit=1', '[[Modification date::+]] OR [[Foo::Foo=Bar]]' ],
+ '[[Modification date::+]] OR [[Foo::Foo=Bar]]'
+ ];
+
+ $provider[] = [
+ [ '[[Modification date::+]] OR <q>[[Foo::Bar]]</q>', '?Modification date=Date', '?Foo=F', 'limit=1' ],
+ '[[Modification date::+]] OR <q>[[Foo::Bar]]</q>'
+ ];
+
+ $provider[] = [
+ [ '[[Has url::http://example.org/api.php?action=Foo]]', '?Has url=url', 'limit=1' ],
+ '[[Has url::http://example.org/api.php?action=Foo]]'
+ ];
+
+ // Produced by smw.org, Template:Invert-property
+ $provider[] = [
+ [ '[[Located in::Foo]]', 'link=none', 'sep=| ]][[Location of::' ],
+ '[[Located in::Foo]]'
+ ];
+
+ $provider[] = [
+ [ '[[Located in::Foo]]', 'link=none', 'sep=| ]][[Location of::', '[[Has url::http://example.org/api.php?action=Foo]]' ],
+ '[[Located in::Foo]][[Has url::http://example.org/api.php?action=Foo]]'
+ ];
+
+ $provider[] = [
+ [ '[[This has a = in it]]', 'link=none', 'sep=| ]][[Location of::', '[[Has url::http://example.org/api.php?action=Foo]]' ],
+ '[[This has a = in it]][[Has url::http://example.org/api.php?action=Foo]]'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/RecurringEventsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/RecurringEventsTest.php
new file mode 100644
index 00000000..70f3dd7b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/RecurringEventsTest.php
@@ -0,0 +1,410 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\ParserParameterFormatter;
+use SMW\RecurringEvents;
+
+/**
+ * @covers \SMW\RecurringEvents
+ * @group semantic-mediawiki
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class RecurringEventsTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ RecurringEvents::class,
+ new RecurringEvents()
+ );
+ }
+
+ /**
+ * @dataProvider getParametersDataProvider
+ *
+ * @since 1.9
+ */
+ public function testGetErrors( array $params, array $expected ) {
+
+ $parameters = new ParserParameterFormatter( $params );
+
+ $instance = new RecurringEvents();
+ $instance->parse( $parameters->toArray() );
+
+ $this->assertCount(
+ $expected['errors'],
+ $instance->getErrors() );
+ }
+
+ /**
+ * @dataProvider getParametersDataProvider
+ *
+ * @since 1.9
+ */
+ public function testGetProperty( array $params, array $expected ) {
+
+ $parameters = new ParserParameterFormatter( $params );
+
+ $instance = new RecurringEvents();
+ $instance->parse( $parameters->toArray() );
+
+ $this->assertEquals(
+ $expected['property'],
+ $instance->getProperty()
+ );
+ }
+
+ /**
+ * @dataProvider getParametersDataProvider
+ *
+ * @since 1.9
+ */
+ public function testGetParameters( array $params, array $expected ) {
+
+ $parameters = new ParserParameterFormatter( $params );
+
+ $instance = new RecurringEvents();
+ $instance->parse( $parameters->toArray() );
+
+ $this->assertEquals(
+ $expected['parameters'],
+ $instance->getParameters()
+ );
+ }
+
+ /**
+ * @dataProvider getParametersDataProvider
+ *
+ * @since 1.9
+ */
+ public function testGetDates( array $params, array $expected ) {
+
+ $parameters = new ParserParameterFormatter( $params );
+
+ $instance = new RecurringEvents();
+ $instance->parse( $parameters->toArray() );
+
+ $this->assertEquals(
+ $expected['dates'],
+ $instance->getDates()
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function getMassInsertDataProvider() {
+ return [
+ [
+ [
+ 'property=Has birthday',
+ 'start=01 Feb 1970',
+ 'Has title=Birthday',
+ 'unit=month', 'period=12',
+ 'limit=500',
+ ],
+ [
+ 'errors' => 0,
+ 'count' => 501,
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ]
+ ];
+ }
+
+ /**
+ * @dataProvider getMassInsertDataProvider
+ *
+ * @since 1.
+ */
+ public function testMassInsert( array $params, array $expected ) {
+
+ $parameters = new ParserParameterFormatter( $params );
+
+ $instance = new RecurringEvents();
+ $instance->parse( $parameters->toArray() );
+
+ $this->assertCount(
+ $expected['count'],
+ $instance->getDates()
+ );
+ }
+
+ /**
+ * @test RecurringEvents::getJulianDay
+ *
+ * @since 1.9
+ */
+ public function testGetJulianDay() {
+ $instance = new RecurringEvents();
+ $instance->parse( [] );
+
+ // SMWDIWikiPage stub object
+ $dataValue = $this->getMockBuilder( 'SMWTimeValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( null ) );
+
+ $this->assertEquals(
+ null,
+ $instance->getJulianDay( $dataValue )
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function getParametersDataProvider() {
+ return [
+ // {{#set_recurring_event:property=Has birthday
+ // |start=01 Feb 1970
+ // |has title= Birthday
+ // |unit=year
+ // |period=12
+ // |limit=3
+ // }}
+ [
+ [
+ 'property=Has birthday',
+ 'start=01 Feb 1970',
+ 'has title=Birthday',
+ 'unit=month',
+ 'period=12',
+ 'limit=3'
+ ],
+ [
+ 'errors' => 0,
+ 'dates' => [ '1 February 1970', '1 February 1971', '1 February 1972', '1 February 1973' ],
+ 'property' => 'Has birthday',
+ 'parameters' => [ 'has title' => [ 'Birthday' ] ]
+ ]
+ ],
+
+ // {{#set_recurring_event:property=Has birthday
+ // |start=01 Feb 1970
+ // |end=01 Feb 1972
+ // |has title= Birthday
+ // |unit=year
+ // |period=12
+ // |limit=3
+ // }}
+ [
+ [
+ 'property=Has birthday',
+ 'start=01 Feb 1970',
+ 'end=01 Feb 1972',
+ 'has title=Birthday',
+ 'unit=month',
+ 'period=12',
+ 'limit=3'
+ ],
+ [
+ 'errors' => 0,
+ 'dates' => [ '1 February 1970', '1 February 1971', '1 February 1972' ],
+ 'property' => 'Has birthday',
+ 'parameters' => [ 'has title' => [ 'Birthday' ] ]
+ ]
+ ],
+
+ // {{#set_recurring_event:property=Has birthday
+ // |start=01 Feb 1970
+ // |end=01 Feb 1972
+ // |has title= Birthday
+ // |unit=year
+ // |week number=2
+ // |period=12
+ // |limit=3
+ // }}
+ [
+ [
+ 'property=Has birthday',
+ 'start=01 Feb 1970',
+ 'end=01 Feb 1972',
+ 'has title=Birthday',
+ 'unit=month',
+ 'week number=2',
+ 'period=12',
+ 'limit=3'
+ ],
+ [
+ 'errors' => 0,
+ 'dates' => [ '1 February 1970', '14 February 1971' ],
+ 'property' => 'Has birthday',
+ 'parameters' => [ 'has title' => [ 'Birthday' ] ]
+ ]
+ ],
+
+ // {{#set_recurring_event:property=Has birthday
+ // |start=01 Feb 1972 02:00
+ // |has title=Test 12
+ // |unit=week
+ // |period=4
+ // |limit=3
+ // }}
+ [
+ [
+ 'property=Has birthday',
+ 'start=01 Feb 1972 02:00',
+ 'has title=Test 2',
+ 'unit=week',
+ 'period=4',
+ 'limit=3'
+ ],
+ [
+ 'errors' => 0,
+ 'dates' => [ '1 February 1972 02:00:00', '29 February 1972 02:00:00', '28 March 1972 02:00:00', '25 April 1972 02:00:00' ],
+ 'property' => 'Has birthday',
+ 'parameters' => [ 'has title' => [ 'Test 2' ] ]
+ ]
+ ],
+
+ // {{#set_recurring_event:property=Has date
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ [
+ [
+ 'property=Has date',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => 0,
+ 'dates' => [ '4 January 2010', '11 January 2010', '1 February 2010', 'March 16, 2010', 'March 23, 2010' ],
+ 'property' => 'Has date',
+ 'parameters' => []
+ ]
+ ],
+
+ // {{#set_recurring_event:property=Has date
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010|+sep=;
+ // |exclude=January 18, 2010;January 25, 2010|+sep=;
+ // }}
+ [
+ [
+ 'property=Has date',
+ 'start=January 4, 2010',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ '+sep=;',
+ 'exclude=January 18, 2010;January 25, 2010',
+ '+sep=;'
+ ],
+ [
+ 'errors' => 0,
+ 'dates' => [ '4 January 2010', '11 January 2010', '1 February 2010', 'March 16, 2010', 'March 23, 2010' ],
+ 'property' => 'Has date',
+ 'parameters' => []
+ ]
+ ],
+
+ // Simulate start date has wrong type
+
+ // {{#set_recurring_event:property=Has date
+ // |start=???
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ [
+ [
+ 'property=Has date',
+ 'start=???',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => 1,
+ 'dates' => [],
+ 'property' => 'Has date',
+ 'parameters' => []
+ ]
+ ],
+
+ // Simulate missing start date
+
+ // {{#set_recurring_event:property=Has date
+ // |start=
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010
+ // |exclude=January 18, 2010;January 25, 2010
+ // }}
+ [
+ [
+ 'property=Has date',
+ 'start=',
+ 'unit=week',
+ 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ 'exclude=January 18, 2010;January 25, 2010'
+ ],
+ [
+ 'errors' => 1,
+ 'dates' => [],
+ 'property' => 'Has date',
+ 'parameters' => []
+ ]
+ ],
+
+ // Simulate missing property
+
+ // {{#set_recurring_event:property=
+ // |start=January 4, 2010
+ // |unit=week
+ // |period=1
+ // |limit=4
+ // |include=March 16, 2010;March 23, 2010|+sep=;
+ // |exclude=January 18, 2010;January 25, 2010|+sep=;
+ // }}
+ [
+ [
+ 'property=',
+ 'start=January 4, 2010',
+ 'unit=week', 'period=1',
+ 'limit=4',
+ 'include=March 16, 2010;March 23, 2010',
+ '+sep=;',
+ 'exclude=January 18, 2010;January 25, 2010',
+ '+sep=;'
+ ],
+ [
+ 'errors' => 1,
+ 'dates' => [],
+ 'property' => '',
+ 'parameters' => []
+ ]
+ ],
+ ];
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/ChangeTitleTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/ChangeTitleTest.php
new file mode 100644
index 00000000..18d2297e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/ChangeTitleTest.php
@@ -0,0 +1,329 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Writer;
+
+use SMWSQLStore3Writers;
+use Title;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @covers \SMWSQLStore3Writers
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-sqlstore
+ * @group mediawiki-databaseless
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class ChangeTitleTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $factory;
+ private $testEnvironment;
+
+ protected function setUp() {
+
+ $nullJob = $this->getMockBuilder( '\SMW\MediaWiki\Jobs\NullJob' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory = $this->getMockBuilder( '\SMW\MediaWiki\JobFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $jobFactory->expects( $this->any() )
+ ->method( 'newUpdateJob' )
+ ->will( $this->returnValue( $nullJob ) );
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->registerObject( 'JobFactory', $jobFactory );
+
+ $entityManager = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityManager->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $entityManager ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $propertyTableRowDiffer = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableRowDiffer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableRowDiffer->expects( $this->any() )
+ ->method( 'computeTableRowDiff' )
+ ->will( $this->returnValue( [ [], [], [] ] ) );
+
+ $propertyTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subobjectListFinder = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\SubobjectListFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subobjectListFinder->expects( $this->any() )
+ ->method( 'find' )
+ ->will( $this->returnValue( [] ) );
+
+ $changePropListener = $this->getMockBuilder( '\SMW\ChangePropListener' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticDataLookup = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\CachingSemanticDataLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeDiff' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff->expects( $this->any() )
+ ->method( 'getTextItems' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeDiff->expects( $this->any() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->any() )
+ ->method( 'newChangeDiff' )
+ ->will( $this->returnValue( $changeDiff ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getDataOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getOrderedDiffByTable' )
+ ->will( $this->returnValue( [] ) );
+
+ $idChanger = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\IdChanger' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->factory = $this->getMockBuilder( '\SMW\SQLStore\SQLStoreFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyStatisticsStore' )
+ ->will( $this->returnValue( $propertyStatisticsStore ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newHierarchyLookup' )
+ ->will( $this->returnValue( $hierarchyLookup ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newSubobjectListFinder' )
+ ->will( $this->returnValue( $subobjectListFinder ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newChangePropListener' )
+ ->will( $this->returnValue( $changePropListener ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyTableRowDiffer' )
+ ->will( $this->returnValue( $propertyTableRowDiffer ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyTableUpdater' )
+ ->will( $this->returnValue( $propertyTableUpdater ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newSemanticDataLookup' )
+ ->will( $this->returnValue( $semanticDataLookup ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newChangeOp' )
+ ->will( $this->returnValue( $changeOp ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newIdChanger' )
+ ->will( $this->returnValue( $idChanger ) );
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWSQLStore3Writers',
+ new SMWSQLStore3Writers( $this->store, $this->factory )
+ );
+ }
+
+ public function testChangeTitleForMainNamespaceWithoutRedirectId() {
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [] ) );
+
+ $objectIdGenerator->expects( $this->at( 0 ) )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 1 ) );
+
+ $objectIdGenerator->expects( $this->at( 1 ) )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 5 ) );
+
+ $objectIdGenerator->expects( $this->at( 1 ) )
+ ->method( 'findRedirect' )
+ ->will( $this->returnValue( 0 ) );
+
+ $objectIdGenerator->expects( $this->never() )
+ ->method( 'deleteRedirect' );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $parentStore, $this->factory );
+
+ $instance->changeTitle(
+ Title::newFromText( __METHOD__ . '-old', NS_MAIN ),
+ Title::newFromText( __METHOD__ . '-new', NS_MAIN ),
+ 9999
+ );
+ }
+
+ public function testChangeTitleForMainNamespaceWithRedirectId() {
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [] ) );
+
+ $objectIdGenerator->expects( $this->at( 0 ) )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 1 ) );
+
+ $objectIdGenerator->expects( $this->at( 1 ) )
+ ->method( 'getSMWPageID' )
+ ->will( $this->returnValue( 5 ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->once() )
+ ->method( 'query' )
+ ->will( $this->returnValue( true ) );
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $parentStore, $this->factory );
+
+ $instance->changeTitle(
+ Title::newFromText( __METHOD__ . '-old', NS_MAIN ),
+ Title::newFromText( __METHOD__ . '-new', NS_MAIN ),
+ 9999,
+ 1111
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DataUpdateTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DataUpdateTest.php
new file mode 100644
index 00000000..995215ee
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DataUpdateTest.php
@@ -0,0 +1,409 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Writer;
+
+use SMW\DIWikiPage;
+use SMWSQLStore3Writers;
+use Title;
+
+/**
+ * @covers \SMWSQLStore3Writers
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group semantic-mediawiki-sqlstore
+ * @group mediawiki-databaseless
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class DataUpdateTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $factory;
+
+ protected function setUp() {
+
+ $entityManager = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $entityManager->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store = $this->getMockBuilder( '\SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $entityManager ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $propertyTableRowDiffer = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableRowDiffer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableRowDiffer->expects( $this->any() )
+ ->method( 'computeTableRowDiff' )
+ ->will( $this->returnValue( [ [], [], [] ] ) );
+
+ $propertyTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subobjectListFinder = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\SubobjectListFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subobjectListFinder->expects( $this->any() )
+ ->method( 'find' )
+ ->will( $this->returnValue( [] ) );
+
+ $changePropListener = $this->getMockBuilder( '\SMW\ChangePropListener' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticDataLookup = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\CachingSemanticDataLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeDiff' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff->expects( $this->any() )
+ ->method( 'getTextItems' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeDiff->expects( $this->any() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->any() )
+ ->method( 'newChangeDiff' )
+ ->will( $this->returnValue( $changeDiff ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getDataOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getOrderedDiffByTable' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->factory = $this->getMockBuilder( '\SMW\SQLStore\SQLStoreFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyStatisticsStore' )
+ ->will( $this->returnValue( $propertyStatisticsStore ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newHierarchyLookup' )
+ ->will( $this->returnValue( $hierarchyLookup ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newSubobjectListFinder' )
+ ->will( $this->returnValue( $subobjectListFinder ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newChangePropListener' )
+ ->will( $this->returnValue( $changePropListener ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyTableRowDiffer' )
+ ->will( $this->returnValue( $propertyTableRowDiffer ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyTableUpdater' )
+ ->will( $this->returnValue( $propertyTableUpdater ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newSemanticDataLookup' )
+ ->will( $this->returnValue( $semanticDataLookup ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newChangeOp' )
+ ->will( $this->returnValue( $changeOp ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWSQLStore3Writers',
+ new SMWSQLStore3Writers( $this->store, $this->factory )
+ );
+ }
+
+ public function testDoDataUpdateForMainNamespaceWithoutSubobject() {
+
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->setConstructorArgs( [ DIWikiPage::newFromTitle( $title ) ] )
+ ->setMethods( null )
+ ->getMock();
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [] ) );
+
+ $objectIdGenerator->expects( $this->once() )
+ ->method( 'getSMWPageIDandSort' )
+ ->will( $this->returnValue( 0 ) );
+
+ $objectIdGenerator->expects( $this->once() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 0 ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $parentStore, $this->factory );
+ $instance->doDataUpdate( $semanticData );
+ }
+
+ public function testDoDataUpdateForConceptNamespaceWithoutSubobject() {
+
+ $title = Title::newFromText( __METHOD__, SMW_NS_CONCEPT );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->setConstructorArgs( [ DIWikiPage::newFromTitle( $title ) ] )
+ ->setMethods( null )
+ ->getMock();
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->any() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [] ) );
+
+ $objectIdGenerator->expects( $this->once() )
+ ->method( 'getSMWPageIDandSort' )
+ ->will( $this->returnValue( 0 ) );
+
+ $objectIdGenerator->expects( $this->once() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 0 ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $parentStore, $this->factory );
+ $instance->doDataUpdate( $semanticData );
+ }
+
+ public function testDoDataUpdateForMainNamespaceWithRedirect() {
+
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->setConstructorArgs( [ DIWikiPage::newFromTitle( $title ) ] )
+ ->setMethods( [ 'getPropertyValues' ] )
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromTitle( $title ) ] ) );
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->once() )
+ ->method( 'getSMWPageIDandSort' )
+ ->will( $this->returnValue( 0 ) );
+
+ $objectIdGenerator->expects( $this->once() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 0 ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $parentStore, $this->factory );
+ $instance->doDataUpdate( $semanticData );
+ }
+
+ public function testAtomicTransactionOnDataUpdate() {
+
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+
+ $semanticData = $this->getMockBuilder( '\SMW\SemanticData' )
+ ->setConstructorArgs( [ DIWikiPage::newFromTitle( $title ) ] )
+ ->setMethods( [ 'getPropertyValues' ] )
+ ->getMock();
+
+ $semanticData->expects( $this->once() )
+ ->method( 'getPropertyValues' )
+ ->will( $this->returnValue( [ DIWikiPage::newFromTitle( $title ) ] ) );
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->atLeastOnce() )
+ ->method( 'getSMWPageIDandSort' )
+ ->will( $this->returnValue( 0 ) );
+
+ $objectIdGenerator->expects( $this->atLeastOnce() )
+ ->method( 'makeSMWPageID' )
+ ->will( $this->returnValue( 0 ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->atLeastOnce() )
+ ->method( 'beginAtomicTransaction' );
+
+ $database->expects( $this->atLeastOnce() )
+ ->method( 'endAtomicTransaction' );
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $parentStore->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $parentStore->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $parentStore, $this->factory );
+ $instance->doDataUpdate( $semanticData );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DeleteSubjectTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DeleteSubjectTest.php
new file mode 100644
index 00000000..729d6694
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SQLStore/Writer/DeleteSubjectTest.php
@@ -0,0 +1,259 @@
+<?php
+
+namespace SMW\Tests\SQLStore\Writer;
+
+use SMWSQLStore3Writers;
+use Title;
+
+/**
+ * @covers \SMWSQLStore3Writers
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class DeleteSubjectTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $factory;
+
+ protected function setUp() {
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $hierarchyLookup = $this->getMockBuilder( '\SMW\HierarchyLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subobjectListFinder = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\SubobjectListFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subobjectListFinder->expects( $this->any() )
+ ->method( 'find' )
+ ->will( $this->returnValue( [] ) );
+
+ $changePropListener = $this->getMockBuilder( '\SMW\ChangePropListener' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->factory = $this->getMockBuilder( '\SMW\SQLStore\SQLStoreFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyStatisticsStore' )
+ ->will( $this->returnValue( $propertyStatisticsStore ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newHierarchyLookup' )
+ ->will( $this->returnValue( $hierarchyLookup ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newSubobjectListFinder' )
+ ->will( $this->returnValue( $subobjectListFinder ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newChangePropListener' )
+ ->will( $this->returnValue( $changePropListener ) );
+
+ $propertyTableIdReferenceFinder = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableIdReferenceFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableInfoFetcher = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableInfoFetcher' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTableInfoFetcher' )
+ ->will( $this->returnValue( $propertyTableInfoFetcher ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'service' )
+ ->with( $this->equalTo( 'PropertyTableIdReferenceFinder' ) )
+ ->will( $this->returnValue( $propertyTableIdReferenceFinder ) );
+
+ $propertyTableRowDiffer = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableRowDiffer' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyTableRowDiffer->expects( $this->any() )
+ ->method( 'computeTableRowDiff' )
+ ->will( $this->returnValue( [ [], [], [] ] ) );
+
+ $propertyTableUpdater = $this->getMockBuilder( '\SMW\SQLStore\PropertyTableUpdater' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $semanticDataLookup = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\CachingSemanticDataLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeDiff' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeDiff->expects( $this->any() )
+ ->method( 'getTextItems' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeDiff->expects( $this->any() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp = $this->getMockBuilder( '\SMW\SQLStore\ChangeOp\ChangeOp' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $changeOp->expects( $this->any() )
+ ->method( 'newChangeDiff' )
+ ->will( $this->returnValue( $changeDiff ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getChangedEntityIdSummaryList' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getDataOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getTableChangeOps' )
+ ->will( $this->returnValue( [] ) );
+
+ $changeOp->expects( $this->any() )
+ ->method( 'getOrderedDiffByTable' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyTableRowDiffer' )
+ ->will( $this->returnValue( $propertyTableRowDiffer ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyTableUpdater' )
+ ->will( $this->returnValue( $propertyTableUpdater ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newSemanticDataLookup' )
+ ->will( $this->returnValue( $semanticDataLookup ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newChangeOp' )
+ ->will( $this->returnValue( $changeOp ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWSQLStore3Writers',
+ new SMWSQLStore3Writers( $this->store, $this->factory )
+ );
+ }
+
+ public function testDeleteSubjectForMainNamespace() {
+
+ $title = Title::newFromText( __METHOD__, NS_MAIN );
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->atLeastOnce() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->will( $this->returnValue( [ 0 ] ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->exactly( 7 ) )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $this->store, $this->factory );
+ $instance->deleteSubject( $title );
+ }
+
+ public function testDeleteSubjectForConceptNamespace() {
+
+ $title = Title::newFromText( __METHOD__, SMW_NS_CONCEPT );
+
+ $objectIdGenerator = $this->getMockBuilder( '\SMWSql3SmwIds' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $objectIdGenerator->expects( $this->atLeastOnce() )
+ ->method( 'findAllEntitiesThatMatch' )
+ ->with(
+ $this->equalTo( $title->getDBkey() ),
+ $this->equalTo( $title->getNamespace() ),
+ $this->equalTo( $title->getInterwiki() ),
+ '' )
+ ->will( $this->returnValue( [ 0 ] ) );
+
+ $database = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $database->expects( $this->exactly( 2 ) )
+ ->method( 'delete' )
+ ->will( $this->returnValue( true ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $database ) );
+
+ $this->store->expects( $this->exactly( 7 ) )
+ ->method( 'getObjectIds' )
+ ->will( $this->returnValue( $objectIdGenerator ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getPropertyTables' )
+ ->will( $this->returnValue( [] ) );
+
+ $this->store->expects( $this->any() )
+ ->method( 'getOptions' )
+ ->will( $this->returnValue( new \SMW\Options() ) );
+
+ $instance = new SMWSQLStore3Writers( $this->store, $this->factory );
+ $instance->deleteSubject( $title );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SemanticDataTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SemanticDataTest.php
new file mode 100644
index 00000000..51a2b794
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SemanticDataTest.php
@@ -0,0 +1,710 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ApplicationFactory;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Localizer;
+use SMW\SemanticData;
+use SMW\Subobject;
+use SMWDITime as DITime;
+use Title;
+
+/**
+ * @covers \SMW\SemanticData
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SemanticDataTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $semanticDataValidator;
+ private $dataValueFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->testEnvironment->addConfiguration( 'smwgCreateProtectionRight', false );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getRedirectTarget' )
+ ->will( $this->returnArgument( 0 ) );
+
+ $this->testEnvironment->registerObject( 'Store', $store );
+
+ $this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testConstructor() {
+
+ $instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $instance
+ );
+
+ $this->assertInstanceOf(
+ 'SMWSemanticData',
+ $instance
+ );
+ }
+
+ public function testGetPropertyValues() {
+
+ $instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
+
+ $this->assertInstanceOf(
+ 'SMW\DIWikiPage',
+ $instance->getSubject()
+ );
+
+ $this->assertEmpty(
+ $instance->getPropertyValues( new DIProperty( 'Foo', true ) )
+ );
+
+ $this->assertEmpty(
+ $instance->getPropertyValues( new DIProperty( 'Foo' ) )
+ );
+ }
+
+ public function testAddPropertyValue() {
+
+ $instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
+
+ $instance->addPropertyValue(
+ 'addPropertyValue',
+ DIWikiPage::doUnserialize( 'Foo#0##' )
+ );
+
+ $key = Localizer::getInstance()->getNamespaceTextById( SMW_NS_PROPERTY ) . ':' . 'addPropertyValue';
+
+ $expected = [
+ 'propertyCount' => 1,
+ 'propertyLabels' => [ $key ],
+ 'propertyValues' => [ 'Foo' ]
+ ];
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance
+ );
+ }
+
+ public function testGetHash() {
+
+ $instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
+
+ $instance->addDataValue(
+ DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' )
+ );
+
+ $subobject = $this->newSubobject( $instance->getSubject()->getTitle() );
+
+ $instance->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $instance->getHash()
+ );
+ }
+
+ public function testPropertyOrderDoesNotInfluenceHash() {
+
+ $instance = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $instance->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $instance->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
+ );
+
+ $instanceToCheck = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $instanceToCheck->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
+ );
+
+ $instanceToCheck->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $this->assertEquals(
+ $instance->getHash(),
+ $instanceToCheck->getHash()
+ );
+ }
+
+ public function testSubSemanticPropertyOrderDoesNotInfluenceHash() {
+
+ $subobject = new Subobject( Title::newFromText( 'Foo' ) );
+ $subobject->setEmptyContainerForId( 'Foo' );
+
+ $subobject->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $subobject->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
+ );
+
+ $instance = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $instance->addSubobject(
+ $subobject
+ );
+
+ $subobject = new Subobject( Title::newFromText( 'Foo' ) );
+ $subobject->setEmptyContainerForId( 'Foo' );
+
+ $subobject->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
+ );
+
+ $subobject->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $instanceToCheck = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $instanceToCheck->addSubobject(
+ $subobject
+ );
+
+ $this->assertEquals(
+ $instance->getHash(),
+ $instanceToCheck->getHash()
+ );
+ }
+
+ public function testThatChangingDataDoesEnforceDifferentHash() {
+
+ $instance = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $firstHash = $instance->getHash();
+
+ $instance->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $secondHash = $instance->getHash();
+
+ $this->assertNotEquals(
+ $firstHash,
+ $secondHash
+ );
+
+ $subobject = new Subobject( Title::newFromText( 'Foo' ) );
+ $subobject->setEmptyContainerForId( 'Foo' );
+
+ $subobject->addDataValue(
+ $this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
+ );
+
+ $instance->addSubSemanticData(
+ $subobject->getSemanticData()
+ );
+
+ $thirdHash = $instance->getHash();
+
+ $this->assertNotEquals(
+ $secondHash,
+ $thirdHash
+ );
+
+ // Remove the data added in the third step and expect
+ // the hash from the second
+ $instance->removeSubSemanticData(
+ $subobject->getSemanticData()
+ );
+
+ $this->assertEquals(
+ $secondHash,
+ $instance->getHash()
+ );
+ }
+
+ public function testGetSubSemanticData() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ // Adds only a subobject reference to the container
+ $subobject = $this->newSubobject( $title );
+
+ $instance->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getSemanticData()->getSubject()
+ );
+
+ $this->assertNotInstanceOf(
+ 'SMWContainerSemanticData',
+ $instance->getSubSemanticData()
+ );
+
+ // Adds a complete container
+ $instance->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ foreach ( $instance->getSubSemanticData() as $subSemanticData ) {
+
+ $this->assertInstanceOf(
+ 'SMWContainerSemanticData',
+ $subSemanticData
+ );
+ }
+ }
+
+ public function testAddAndRemoveSubSemanticData() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ // Adds only a subobject reference to the container
+ $subobject = $this->newSubobject( $title );
+
+ $instance->addSubobject( $subobject );
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getSubSemanticData()
+ );
+
+ foreach ( $instance->getSubSemanticData() as $subSemanticData ) {
+
+ $this->assertInstanceOf(
+ 'SMWContainerSemanticData',
+ $subSemanticData
+ );
+
+ $this->assertEquals(
+ $subSemanticData,
+ $subobject->getSemanticData()
+ );
+ }
+
+ $instance->removeSubSemanticData( $subobject->getSemanticData() );
+
+ $this->assertNotInstanceOf(
+ 'SMWContainerSemanticData',
+ $instance->getSubSemanticData()
+ );
+ }
+
+ public function testAddSubSemanticDataWithOutSubobjectNameThrowsException() {
+
+ $instance = new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) ) );
+
+ $this->setExpectedException( '\SMW\Exception\SubSemanticDataException' );
+
+ $instance->addSubSemanticData(
+ new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( 'addSubSemanticData' ) ) )
+ );
+ }
+
+ public function testDifferentSubSemanticDataSubjectThrowsException() {
+
+ $instance = new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) ) );
+
+ $this->setExpectedException( '\SMW\Exception\SubSemanticDataException' );
+ $instance->addSubobject( $this->newSubobject( Title::newFromText( 'addSubSemanticData' ) ) );
+ }
+
+ public function testImportDataFromForDifferentSubjectThrowsException() {
+
+ $instance = new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) ) );
+
+ $this->setExpectedException( '\SMW\Exception\SemanticDataImportException' );
+
+ $instance->importDataFrom(
+ new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( 'importDataFrom' ) ) )
+ );
+ }
+
+ public function testHasAndFindSubSemanticData() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ $subobject = $this->newSubobject( $title );
+ $subobjectName = $subobject->getSemanticData()->getSubject()->getSubobjectName();
+
+ $this->assertFalse( $instance->hasSubSemanticData() );
+ $this->assertEmpty( $instance->findSubSemanticData( $subobjectName ));
+
+ // Adds only a subobject reference to the container
+ $instance->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getSemanticData()->getSubject()
+ );
+
+ $this->assertFalse( $instance->hasSubSemanticData( $subobjectName ) );
+ $this->assertEmpty( $instance->findSubSemanticData( $subobjectName ) );
+
+ $instance->addSubSemanticData( $subobject->getSemanticData() );
+
+ $this->assertTrue( $instance->hasSubSemanticData( $subobjectName ) );
+ $this->assertNotEmpty($instance->findSubSemanticData( $subobjectName ) );
+
+ $this->assertInstanceOf(
+ 'SMWContainerSemanticData',
+ $instance->findSubSemanticData( $subobjectName )
+ );
+ }
+
+ public function testSubSemanticDataForNonStringSubobjectName() {
+
+ $instance = new SemanticData(
+ DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) )
+ );
+
+ $this->assertFalse(
+ $instance->hasSubSemanticData( new \stdClass )
+ );
+
+ $this->assertEmpty(
+ $instance->findSubSemanticData( new \stdClass )
+ );
+ }
+
+ public function testSetLastModified() {
+
+ $instance = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $instance->setOption( SemanticData::OPT_LAST_MODIFIED, 1001 );
+
+ $this->assertEquals(
+ 1001,
+ $instance->getOption( SemanticData::OPT_LAST_MODIFIED )
+ );
+ }
+
+ public function testGetLastModifiedFromModificationDate() {
+
+ $instance = new SemanticData(
+ new DIWikiPage( 'Foo', NS_MAIN )
+ );
+
+ $instance->addPropertyObjectValue(
+ new DIProperty( '_MDAT' ),
+ DITime::newFromTimestamp( 1272508903 )
+ );
+
+ $this->assertEquals(
+ 1272508903,
+ $instance->getOption( SemanticData::OPT_LAST_MODIFIED )
+ );
+ }
+
+ public function testVisibility() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ $instance->addDataValue(
+ DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' )
+ );
+
+ $this->assertTrue(
+ $instance->hasVisibleProperties()
+ );
+
+ $instance->addSubobject(
+ $this->newSubobject( $title )
+ );
+
+ $this->assertTrue(
+ $instance->hasVisibleSpecialProperties()
+ );
+ }
+
+ /**
+ * @dataProvider removePropertyObjectProvider
+ */
+ public function testRemovePropertyObjectValue( $title, $property, $dataItem ) {
+
+ $instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ $instance->addPropertyObjectValue( $property, $dataItem );
+ $this->assertFalse( $instance->isEmpty() );
+
+ $instance->removePropertyObjectValue( $property, $dataItem );
+ $this->assertTrue( $instance->isEmpty() );
+ }
+
+ public function testRemoveProperty() {
+
+ $property = new DIProperty( 'Foo' );
+ $instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
+
+ $instance->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( 'Bar', NS_MAIN, '', 'Foobar' )
+ );
+
+ $this->assertTrue(
+ $instance->hasProperty( $property )
+ );
+
+ $instance->removeProperty( $property );
+
+ $this->assertFalse(
+ $instance->hasProperty( $property )
+ );
+ }
+
+ public function testGetPropertyValuesToReturnAnUnmappedArray() {
+
+ $property = new DIProperty( 'Foo' );
+ $instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
+
+ $instance->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( 'Bar', NS_MAIN )
+ );
+
+ $this->assertArrayHasKey(
+ 0,
+ $instance->getPropertyValues( $property )
+ );
+ }
+
+ public function testClear() {
+
+ $title = Title::newFromText( __METHOD__ );
+ $instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ $instance->addPropertyObjectValue(
+ new DIProperty( '_MDAT' ),
+ DITime::newFromTimestamp( 1272508903 )
+ );
+
+ $this->assertFalse( $instance->isEmpty() );
+
+ $instance->clear();
+ $this->assertTrue( $instance->isEmpty() );
+ }
+
+ public function testExtensionData() {
+
+ $instance = new SemanticData(
+ DIWikiPage::newFromText( __METHOD__ )
+ );
+
+ $instance->setExtensionData( 'Foo', 42 );
+
+ $this->assertEquals(
+ 42,
+ $instance->getExtensionData( 'Foo' )
+ );
+
+ $callback = function() { return 42; };
+
+ $instance->setExtensionData( 'Bar', $callback );
+
+ $this->assertEquals(
+ $callback,
+ $instance->getExtensionData( 'Bar' )
+ );
+ }
+
+ /**
+ * @dataProvider dataValueDataProvider
+ */
+ public function testAddDataValues( $dataValues, $expected ) {
+
+ $title = Title::newFromText( __METHOD__ );
+ $instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ foreach ( $dataValues as $dataValue ) {
+ $instance->addDataValue( $dataValue );
+ }
+
+ if ( $expected['error'] > 0 ) {
+ return $this->assertCount( $expected['error'], $instance->getErrors() );
+ }
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function removePropertyObjectProvider() {
+ ApplicationFactory::clear();
+
+ $provider = [];
+
+ $title = Title::newFromText( __METHOD__ );
+ $subobject = $this->newSubobject( $title, __METHOD__, '999' );
+
+ // #0
+ $provider[] = [
+ $title,
+ new DIProperty( '_MDAT'),
+ DITime::newFromTimestamp( 1272508903 )
+ ];
+
+ // #1
+ $provider[] = [
+ $title,
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function dataValueDataProvider() {
+ ApplicationFactory::clear();
+
+ $provider = [];
+
+ // #0 Single DataValue is added
+ $provider[] = [
+ [
+ DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
+ ],
+ [
+ 'error' => 0,
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => 'Bar'
+ ]
+ ];
+
+ // #1 Equal Datavalues will only result in one added object
+ $provider[] = [
+ [
+ DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
+ DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
+ ],
+ [
+ 'error' => 0,
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => 'Bar'
+ ]
+ ];
+
+ // #2 Two different DataValue objects
+ $provider[] = [
+ [
+ DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
+ DataValueFactory::getInstance()->newDataValueByText( 'Lila', 'Lula' ),
+ ],
+ [
+ 'error' => 0,
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 'Foo', 'Lila' ],
+ 'propertyValues' => [ 'Bar', 'Lula' ]
+ ]
+ ];
+
+ // #3 Error (Inverse)
+ $provider[] = [
+ [
+ DataValueFactory::getInstance()->newDataValueByText( '-Foo', 'Bar' ),
+ ],
+ [
+ 'error' => 1,
+ 'propertyCount' => 0,
+ ]
+ ];
+
+ // #4 One valid DataValue + an error object
+ $provider[] = [
+ [
+ DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
+ DataValueFactory::getInstance()->newDataValueByText( '-Foo', 'bar' ),
+ ],
+ [
+ 'error' => 1,
+ 'propertyCount' => 1,
+ 'propertyLabels' => [ 'Foo' ],
+ 'propertyValues' => [ 'Bar' ]
+ ]
+ ];
+
+
+ // #5 Error (Predefined)
+ $provider[] = [
+ [
+ DataValueFactory::getInstance()->newDataValueByText( '_Foo', 'Bar' ),
+ ],
+ [
+ 'error' => 1,
+ 'propertyCount' => 0,
+ ]
+ ];
+
+ // #6 Error (Known predefined property)
+ $provider[] = [
+ [
+ DataValueFactory::getInstance()->newDataValueByText( 'Modification date', 'Bar' ),
+ ],
+ [
+ 'error' => 1,
+ 'propertyCount' => 0,
+ ]
+ ];
+
+ return $provider;
+ }
+
+ private function newSubobject( Title $title, $property = 'Quuy', $value = 'Xeer' ) {
+
+ $subobject = new Subobject( $title );
+ $subobject->setEmptyContainerForId( 'Foo' );
+
+ $subobject->addDataValue(
+ DataValueFactory::getInstance()->newDataValueByText( $property, $value )
+ );
+
+ return $subobject;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SettingsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SettingsTest.php
new file mode 100644
index 00000000..d0e10722
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SettingsTest.php
@@ -0,0 +1,184 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\Settings;
+use SMW\Tests\TestEnvironment;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\Settings
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SettingsTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ protected function tearDown() {
+ Settings::clear();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider settingsProvider
+ */
+ public function testCanConstruct( array $settings ) {
+
+ $instance = Settings::newFromArray( $settings );
+
+ $this->assertInstanceOf(
+ '\SMW\Settings',
+ $instance
+ );
+
+ $this->assertFalse(
+ $instance === Settings::newFromArray( $settings )
+ );
+ }
+
+ /**
+ * @dataProvider settingsProvider
+ */
+ public function testGet( array $settings ) {
+
+ $instance = Settings::newFromArray( $settings );
+
+ foreach ( $settings as $name => $value ) {
+ $this->assertEquals( $value, $instance->get( $name ) );
+ }
+
+ $this->assertTrue( true );
+ }
+
+ public function testUnknownSettingThrowsException() {
+
+ $instance = Settings::newFromArray( [ 'Foo' => 'bar' ] );
+
+ $this->setExpectedException( '\SMW\Exception\SettingNotFoundException' );
+ $instance->get( 'foo' );
+ }
+
+ public function testSafeGetOnUnknownSetting() {
+
+ $instance = Settings::newFromArray( [ 'Foo' => 'bar' ] );
+
+ $this->assertFalse(
+ $instance->safeGet( 'foo', false )
+ );
+ }
+
+ /**
+ * @dataProvider settingsProvider
+ */
+ public function testSet( array $settings ) {
+
+ $instance = Settings::newFromArray( [] );
+
+ foreach ( $settings as $name => $value ) {
+ $instance->set( $name, $value );
+ $this->assertEquals( $value, $instance->get( $name ) );
+ }
+
+ $this->assertTrue( true );
+ }
+
+ /**
+ * @dataProvider globalsSettingsProvider
+ */
+ public function testNewFromGlobals( array $settings ) {
+
+ $instance = Settings::newFromGlobals();
+
+ // Assert that newFromGlobals is a static instance
+ $this->assertTrue(
+ $instance === Settings::newFromGlobals()
+ );
+
+ // Reset instance
+ $instance->clear();
+ $this->assertTrue( $instance !== Settings::newFromGlobals() );
+
+ foreach ( $settings as $key => $value ) {
+ $this->assertTrue( $instance->has( $key ), "Failed asserting that {$key} exists" );
+ }
+ }
+
+ /**
+ * @dataProvider nestedSettingsProvider
+ */
+ public function testNestedSettingsIteration( $test, $key, $expected ) {
+
+ $instance = Settings::newFromArray( $test );
+
+ $this->assertInternalType( $expected['type'], $instance->get( $key ) );
+ $this->assertEquals( $expected['value'], $instance->get( $key ) );
+ }
+
+ /**
+ * @return array
+ */
+ public function nestedSettingsProvider() {
+
+ $testEnvironment = new TestEnvironment();
+ $utilityFactory = $testEnvironment->getUtilityFactory();
+
+ $Foo = $utilityFactory->createRandomString();
+ $Lula = $utilityFactory->createRandomString();
+ $Lala = $utilityFactory->createRandomString();
+
+ $child = [ 'Lisa', 'Lula', [ 'Lila' ] ];
+ $parent = [ 'child' => $child ];
+
+ $Lila = [ 'Lala' => $Lala, 'parent' => $parent ];
+ $Bar = [ 'Lula' => $Lula, 'Lila' => $Lila ];
+ $test = [ 'Foo' => $Foo, 'Bar' => $Bar ];
+
+ return [
+ [ $test, 'Foo', [ 'type' => 'string', 'value' => $Foo ] ],
+ [ $test, 'Bar', [ 'type' => 'array', 'value' => $Bar ] ],
+ [ $test, 'Lula', [ 'type' => 'string', 'value' => $Lula ] ],
+ [ $test, 'Lila', [ 'type' => 'array', 'value' => $Lila ] ],
+ [ $test, 'Lala', [ 'type' => 'string', 'value' => $Lala ] ],
+ [ $test, 'parent', [ 'type' => 'array', 'value' => $parent ] ],
+ [ $test, 'child', [ 'type' => 'array', 'value' => $child ] ]
+ ];
+ }
+
+ /**
+ * Provides sample data to be tested
+ *
+ * @return array
+ */
+ public function settingsProvider() {
+ return [ [ [
+ 'foo' => 'bar',
+ 'baz' => 'BAH',
+ 'bar' => [ '9001' ],
+ 'foo' => [ '9001', [ 9001, 4.2 ] ],
+ '~[,,_,,]:3' => [ 9001, 4.2 ],
+ ] ] ];
+ }
+
+ /**
+ * Provides and collects individual smwg* settings
+ *
+ * @return array
+ */
+ public function globalsSettingsProvider() {
+
+ $settings = array_intersect_key( $GLOBALS,
+ array_flip( preg_grep('/^smwg/', array_keys( $GLOBALS ) ) )
+ );
+
+ unset( $settings['smwgDeprecationNotices'] );
+
+ return [ [ $settings ] ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SetupTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SetupTest.php
new file mode 100644
index 00000000..d9cf96fc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SetupTest.php
@@ -0,0 +1,344 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\ApplicationFactory;
+use SMW\Setup;
+
+/**
+ * @covers \SMW\Setup
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @group medium
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SetupTest extends \PHPUnit_Framework_TestCase {
+
+ private $applicationFactory;
+ private $defaultConfig;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $store->expects( $this->any() )
+ ->method( 'getProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $store->expects( $this->any() )
+ ->method( 'getInProperties' )
+ ->will( $this->returnValue( [] ) );
+
+ $language = $this->getMockBuilder( '\Language' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->applicationFactory = ApplicationFactory::getInstance();
+ $this->applicationFactory->registerObject( 'Store', $store );
+
+ $this->defaultConfig = [
+ 'smwgMainCacheType' => CACHE_NONE,
+ 'smwgNamespacesWithSemanticLinks' => [],
+ 'smwgEnableUpdateJobs' => false,
+ 'wgNamespacesWithSubpages' => [],
+ 'wgExtensionAssetsPath' => false,
+ 'smwgResourceLoaderDefFiles' => [],
+ 'wgResourceModules' => [],
+ 'wgScriptPath' => '/Foo',
+ 'wgServer' => 'http://example.org',
+ 'wgVersion' => '1.21',
+ 'wgLanguageCode' => 'en',
+ 'wgLang' => $language,
+ 'IP' => 'Foo',
+ 'smwgSemanticsEnabled' => true,
+ 'smwgConfigFileDir' => ''
+ ];
+
+ foreach ( $this->defaultConfig as $key => $value ) {
+ $this->applicationFactory->getSettings()->set( $key, $value );
+ }
+ }
+
+ protected function tearDown() {
+ $this->applicationFactory->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $applicationFactory = $this->getMockBuilder( '\SMW\ApplicationFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ Setup::class,
+ new Setup( $applicationFactory )
+ );
+ }
+
+ public function testResourceModules() {
+
+ $config = $this->defaultConfig;
+ $config['smwgResourceLoaderDefFiles'] = $GLOBALS['smwgResourceLoaderDefFiles'];
+
+ $instance = new Setup( $this->applicationFactory );
+ $instance->init( $config, '' );
+
+ $this->assertNotEmpty(
+ $config['wgResourceModules']
+ );
+ }
+
+ /**
+ * @dataProvider apiModulesDataProvider
+ */
+ public function testGetAPIModules( $name ) {
+
+ $vars = Setup::getAPIModules();
+
+ $this->assertArrayHasKey(
+ $name,
+ $vars
+ );
+ }
+
+ /**
+ * @dataProvider jobClassesDataProvider
+ */
+ public function testRegisterJobClasses( $jobEntry, $setup ) {
+ $this->assertArrayEntryExists( 'wgJobClasses', $jobEntry, $setup );
+ }
+
+ /**
+ * @dataProvider specialPageDataProvider
+ */
+ public function testInitSpecialPageList( $name ) {
+
+ $vars = [];
+
+ Setup::initSpecialPageList( $vars );
+
+ $this->assertArrayHasKey(
+ $name,
+ $vars
+ );
+ }
+
+ public function testRegisterDefaultRightsUserGroupPermissions() {
+
+ $config = $this->defaultConfig;
+
+ $instance = new Setup( $this->applicationFactory );
+ $instance->init( $config, 'Foo' );
+
+ $this->assertNotEmpty(
+ $config['wgAvailableRights']
+ );
+
+ $this->assertTrue(
+ $config['wgGroupPermissions']['sysop']['smw-admin']
+ );
+
+ $this->assertTrue(
+ $config['wgGroupPermissions']['smwcurator']['smw-patternedit']
+ );
+
+ $this->assertTrue(
+ $config['wgGroupPermissions']['smwcurator']['smw-pageedit']
+ );
+
+ $this->assertTrue(
+ $config['wgGroupPermissions']['smwadministrator']['smw-admin']
+ );
+ }
+
+ public function testNoResetOfAlreadyRegisteredGroupPermissions() {
+
+ // Avoid re-setting permissions, refs #1137
+ $localConfig['wgGroupPermissions']['sysop']['smw-admin'] = false;
+ $localConfig['wgGroupPermissions']['smwadministrator']['smw-admin'] = false;
+
+ $localConfig = array_merge(
+ $this->defaultConfig,
+ $localConfig
+ );
+
+ $instance = new Setup( $this->applicationFactory );
+ $instance->init( $localConfig, 'Foo' );
+
+ $this->assertFalse(
+ $localConfig['wgGroupPermissions']['sysop']['smw-admin']
+ );
+
+ $this->assertFalse(
+ $localConfig['wgGroupPermissions']['smwadministrator']['smw-admin']
+ );
+
+ }
+
+ public function testRegisterParamDefinitions() {
+
+ $config = $this->defaultConfig;
+
+ $config['wgParamDefinitions']['smwformat'] = '';
+
+ $this->assertEmpty(
+ $config['wgParamDefinitions']['smwformat']
+ );
+
+ $instance = new Setup( $this->applicationFactory );
+ $instance->init( $config, 'Foo' );
+
+ $this->assertNotEmpty(
+ $config['wgParamDefinitions']['smwformat']
+ );
+ }
+
+ public function testRegisterFooterIcon() {
+
+ $config = $this->defaultConfig;
+
+ $config['wgFooterIcons']['poweredby'] = [];
+
+ $instance = new Setup( $this->applicationFactory );
+ $instance->init( $config, 'Foo' );
+
+ $this->assertNotEmpty(
+ $config['wgFooterIcons']['poweredby']['semanticmediawiki']
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function specialPageDataProvider() {
+
+ $specials = [
+ 'Ask',
+ 'Browse',
+ 'PageProperty',
+ 'SearchByProperty',
+ 'SMWAdmin',
+ 'Concepts',
+ 'ExportRDF',
+ 'Types',
+ 'URIResolver',
+ 'Properties',
+ 'UnusedProperties',
+ 'WantedProperties',
+ 'DeferredRequestDispatcher',
+ 'ProcessingErrorList',
+ 'PropertyLabelSimilarity'
+ ];
+
+ return $this->buildDataProvider( 'wgSpecialPages', $specials, '' );
+ }
+
+ /**
+ * @return array
+ */
+ public function jobClassesDataProvider() {
+
+ $jobs = [
+
+ 'smw.update',
+ 'smw.refresh',
+ 'smw.updateDispatcher',
+ 'smw.parserCachePurge',
+ 'smw.fulltextSearchTableUpdate',
+ 'smw.entityIdDisposer',
+ 'smw.propertyStatisticsRebuild',
+ 'smw.fulltextSearchTableRebuild',
+ 'smw.changePropagationDispatch',
+ 'smw.changePropagationUpdate',
+ 'smw.changePropagationClassUpdate',
+ 'smw.elasticIndexerRecovery',
+ 'smw.elasticFileIngest',
+
+ // Legacy
+ 'SMW\UpdateJob',
+ 'SMW\RefreshJob',
+ 'SMW\UpdateDispatcherJob',
+ 'SMW\ParserCachePurgeJob',
+ 'SMW\FulltextSearchTableUpdateJob',
+ 'SMW\EntityIdDisposerJob',
+ 'SMW\PropertyStatisticsRebuildJob',
+ 'SMW\FulltextSearchTableRebuildJob',
+ 'SMW\ChangePropagationDispatchJob',
+ 'SMW\ChangePropagationUpdateJob',
+ 'SMW\ChangePropagationClassUpdateJob',
+ 'SMWUpdateJob',
+ 'SMWRefreshJob',
+ ];
+
+ return $this->buildDataProvider( 'wgJobClasses', $jobs, '' );
+ }
+
+ /**
+ * @return array
+ */
+ public function apiModulesDataProvider() {
+
+ $modules = [
+ 'ask',
+ 'smwinfo',
+ 'askargs',
+ 'browsebysubject',
+ 'browsebyproperty'
+ ];
+
+ return $this->buildDataProvider( 'wgAPIModules', $modules, '' );
+ }
+
+ private function assertArrayEntryExists( $target, $entry, $config, $type = 'class' ) {
+
+ $config = $config + $this->defaultConfig;
+
+ $this->assertEmpty(
+ $config[$target][$entry],
+ "Asserts that {$entry} is empty"
+ );
+
+ $instance = new Setup( $this->applicationFactory );
+ $instance->init( $config, 'Foo' );
+
+ $this->assertNotEmpty( $config[$target][$entry] );
+
+ switch ( $type ) {
+ case 'class':
+ $this->assertTrue( class_exists( $config[$target][$entry] ) );
+ break;
+ case 'file':
+ $this->assertTrue( file_exists( $config[$target][$entry] ) );
+ break;
+ }
+ }
+
+ /**
+ * @return array
+ */
+ private function buildDataProvider( $id, $definitions, $default ) {
+
+ $provider = [];
+
+ foreach ( $definitions as $definition ) {
+ $provider[] = [
+ $definition,
+ [ $id => [ $definition => $default ] ],
+ ];
+ }
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SubobjectTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SubobjectTest.php
new file mode 100644
index 00000000..7f4307eb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/SubobjectTest.php
@@ -0,0 +1,436 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DataValueFactory;
+use SMW\Subobject;
+use SMW\Tests\Utils\UtilityFactory;
+use SMWDIBlob;
+use Title;
+
+/**
+ * @covers \SMW\Subobject
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SubobjectTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $semanticDataValidator;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->semanticDataValidator = UtilityFactory::getInstance()->newValidatorFactory()->newSemanticDataValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $title = $this->getMockBuilder( 'Title' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMW\Subobject',
+ new Subobject( $title )
+ );
+ }
+
+ public function testSetSemanticWithInvalidIdThrowsException() {
+
+ $instance = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $this->setExpectedException( 'InvalidArgumentException' );
+ $instance->setSemanticData( '' );
+ }
+
+ public function testSetEmptySemanticData() {
+
+ $instance = new Subobject( Title::newFromText( __METHOD__ ) );
+ $instance->setEmptyContainerForId( 'Foo' );
+
+ $this->assertInstanceOf(
+ '\Title',
+ $instance->getTitle()
+ );
+
+ $this->assertInstanceOf(
+ '\SMWContainerSemanticData',
+ $instance->getSemanticData()
+ );
+
+ $this->assertEquals(
+ $instance->getSubobjectId(),
+ $instance->getSemanticData()->getSubject()->getSubobjectName()
+ );
+ }
+
+ /**
+ * @dataProvider getDataProvider
+ */
+ public function testgetSubobjectId( array $parameters, array $expected ) {
+
+ $instance = $this->acquireInstanceForId(
+ Title::newFromText( __METHOD__ ),
+ $parameters['identifier']
+ );
+
+ if ( $expected['identifier'] !== '_' ) {
+ return $this->assertEquals( $expected['identifier'], $instance->getSubobjectId() );
+ }
+
+ $this->assertEquals(
+ $expected['identifier'],
+ substr( $instance->getSubobjectId(), 0, 1 )
+ );
+ }
+
+ /**
+ * @dataProvider getDataProvider
+ */
+ public function testGetProperty( array $parameters ) {
+
+ $instance = $this->acquireInstanceForId(
+ Title::newFromText( __METHOD__ ),
+ $parameters['identifier']
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\DIProperty',
+ $instance->getProperty()
+ );
+ }
+
+ /**
+ * @dataProvider getDataProvider
+ */
+ public function testAddDataValue( array $parameters, array $expected ) {
+
+ $instance = $this->acquireInstanceForId(
+ Title::newFromText( __METHOD__ ),
+ $parameters['identifier']
+ );
+
+ foreach ( $parameters['properties'] as $property => $value ){
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByText(
+ $property,
+ $value
+ );
+
+ $instance->addDataValue( $dataValue );
+ }
+
+ $this->assertCount(
+ $expected['errors'],
+ $instance->getErrors()
+ );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ /**
+ * @dataProvider newDataValueProvider
+ */
+ public function testDataValueExaminer( array $parameters, array $expected ) {
+
+ $property = $this->getMockBuilder( '\SMW\DIProperty' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $property->expects( $this->atLeastOnce() )
+ ->method( 'findPropertyTypeID' )
+ ->will( $this->returnValue( $parameters['property']['typeId'] ) );
+
+ $property->expects( $this->atLeastOnce() )
+ ->method( 'getKey' )
+ ->will( $this->returnValue( $parameters['property']['key'] ) );
+
+ $property->expects( $this->atLeastOnce() )
+ ->method( 'getLabel' )
+ ->will( $this->returnValue( $parameters['property']['label'] ) );
+
+ $dataValue = DataValueFactory::getInstance()->newDataValueByItem(
+ $parameters['dataItem'],
+ $property
+ );
+
+ $instance = $this->acquireInstanceForId(
+ Title::newFromText( __METHOD__ ),
+ 'Foo'
+ );
+
+ $instance->addDataValue( $dataValue );
+
+ $this->assertCount( $expected['errors'], $instance->getErrors() );
+
+ $this->semanticDataValidator->assertThatPropertiesAreSet(
+ $expected,
+ $instance->getSemanticData()
+ );
+ }
+
+ public function testAddDataValueWithInvalidSemanticDataThrowsException() {
+
+ $dataValue = $this->getMockBuilder( '\SMWDataValue' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $instance = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $this->setExpectedException( '\SMW\Exception\SubSemanticDataException' );
+ $instance->addDataValue( $dataValue );
+ }
+
+ public function testGetSemanticDataInvalidSemanticDataThrowsException() {
+
+ $instance = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ $this->setExpectedException( '\SMW\Exception\SubSemanticDataException' );
+ $instance->getSemanticData();
+ }
+
+ /**
+ * @dataProvider errorProvider
+ */
+ public function testErrorHandlingOnErrors( $errors, $expected ) {
+
+ $instance = new Subobject( Title::newFromText( __METHOD__ ) );
+
+ foreach ( $errors as $error ) {
+ $instance->addError( $error );
+ }
+
+ $this->assertCount(
+ $expected,
+ $instance->getErrors()
+ );
+ }
+
+ /**
+ * @dataProvider getDataProvider
+ */
+ public function testGetContainer( array $parameters ) {
+ $instance = $this->acquireInstanceForId(
+ Title::newFromText( __METHOD__ ),
+ $parameters['identifier']
+ );
+
+ $this->assertInstanceOf(
+ '\SMWDIContainer',
+ $instance->getContainer()
+ );
+ }
+
+ public function getDataProvider() {
+
+ $provider = [];
+
+ // #0 / asserting conditions for a named identifier
+ $provider[] = [
+ [
+ 'identifier' => 'Bar',
+ 'properties' => [ 'Foo' => 'bar' ]
+ ],
+ [
+ 'errors' => 0,
+ 'identifier' => 'Bar',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Foo',
+ 'propertyValues' => 'Bar',
+ ]
+ ];
+
+ // #1 / asserting conditions for an anon identifier
+ $provider[] = [
+ [
+ 'identifier' => '',
+ 'properties' => [ 'FooBar' => 'bar Foo' ]
+ ],
+ [
+ 'errors' => 0,
+ 'identifier' => '_',
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'FooBar',
+ 'propertyValues' => 'Bar Foo',
+ ]
+ ];
+
+ // #2 / asserting conditions
+ $provider[] = [
+ [
+ 'identifier' => 'foo',
+ 'properties' => [ 9001 => 1001 ]
+ ],
+ [
+ 'errors' => 0,
+ 'identifier' => 'foo',
+ 'propertyCount' => 1,
+ 'propertyLabels' => [ 9001 ],
+ 'propertyValues' => [ 1001 ],
+ ]
+ ];
+
+ // #3
+ $provider[] = [
+ [
+ 'identifier' => 'foo bar',
+ 'properties' => [ 1001 => 9001, 'Foo' => 'Bar' ]
+ ],
+ [
+ 'errors' => 0,
+ 'identifier' => 'foo bar',
+ 'propertyCount' => 2,
+ 'propertyLabels' => [ 1001, 'Foo' ],
+ 'propertyValues' => [ 9001, 'Bar' ],
+ ]
+ ];
+
+ // #4 / asserting that a property with a leading underscore would produce an error
+ $provider[] = [
+ [
+ 'identifier' => 'bar',
+ 'properties' => [ '_FooBar' => 'bar Foo' ]
+ ],
+ [
+ 'errors' => 1,
+ 'identifier' => 'bar',
+ 'propertyCount' => 1,
+ 'strictPropertyValueMatch' => false,
+ 'propertyKeys' => [ '_ERRC' ]
+ ]
+ ];
+
+ // #5 / asserting that an inverse property would produce an error
+ $provider[] = [
+ [
+ 'identifier' => 'bar',
+ 'properties' => [ '-FooBar' => 'bar Foo' ]
+ ],
+ [
+ 'errors' => 1,
+ 'identifier' => 'bar',
+ 'propertyCount' => 1,
+ 'strictPropertyValueMatch' => false,
+ 'propertyKeys' => [ '_ERRC' ]
+ ]
+ ];
+
+ // #6 / asserting that an improper value for a _wpg property would add "Has improper value for"
+ $provider[] = [
+ [
+ 'identifier' => 'bar',
+ 'properties' => [ 'Foo' => '' ]
+ ],
+ [
+ 'identifier' => 'bar',
+ 'errors' => 1,
+ 'strictPropertyValueMatch' => false,
+ 'propertyCount' => 1,
+ 'propertyKeys' => [ '_ERRC' ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * Provides sample data for various dataItem/datValues
+ *
+ * @return array
+ */
+ public function newDataValueProvider() {
+
+ $provider = [];
+
+ // #0 Bug 49530
+ $provider[] = [
+ [
+ 'property' => [
+ 'typeId' => '_txt',
+ 'label' => 'Blob.example',
+ 'key' => 'Blob.example'
+ ],
+ 'dataItem' => new SMWDIBlob( '<a href="http://username@example.org/path">Example</a>' )
+ ],
+ [
+ 'errors' => 0,
+ 'propertyCount' => 1,
+ 'propertyLabels' => 'Blob.example',
+ 'propertyValues' => '<a href="http://username@example.org/path">Example</a>',
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return Subobject
+ */
+ private function acquireInstanceForId( Title $title, $id = '' ) {
+
+ $instance = new Subobject( $title );
+
+ if ( $id === '' && $id !== null ) {
+ $id = '_abcdef';
+ }
+
+ $instance->setEmptyContainerForId( $id );
+
+ return $instance;
+ }
+
+ public function errorProvider() {
+
+ $provider = [];
+
+ #0
+ $provider[] = [
+ [
+ 'Foo',
+ 'Foo'
+ ],
+ 1
+ ];
+
+ #1
+ $provider[] = [
+ [
+ 'Foo',
+ 'Bar'
+ ],
+ 2
+ ];
+
+ #2
+ $provider[] = [
+ [
+ [ 'Foo' => 'Bar' ],
+ [ 'Foo' => 'Bar' ],
+ ],
+ 1
+ ];
+
+ #3
+ $provider[] = [
+ [
+ [ 'Foo' => 'Bar' ],
+ [ 'Bar' => 'Foo' ],
+ ],
+ 2
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/CommonDataItemTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/CommonDataItemTest.php
new file mode 100644
index 00000000..20664d3a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/CommonDataItemTest.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @covers \SMWDataItem
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class CommonDataItemTest extends \PHPUnit_Framework_TestCase {
+
+ public function testSerializationToFilterSameStringRepresentation() {
+
+ $items = [];
+
+ foreach ( [ 'Foo', 'Bar', 'Foo' ] as $value ) {
+
+ $dataItem = $this->getMockBuilder( '\SMWDataItem' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $dataItem->expects( $this->any() )
+ ->method( 'getSerialization' )
+ ->will( $this->returnValue( $value ) );
+
+ $items[] = $dataItem;
+ }
+
+ $this->assertCount(
+ 2,
+ array_unique( $items )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIConceptTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIConceptTest.php
new file mode 100644
index 00000000..1570458a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIConceptTest.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @covers \SMW\DIConcept
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group SMWDataItems
+ *
+ * @license GNU GPL v2+
+ * @author mwjames
+ */
+class DIConceptTest extends DataItemTest {
+
+ /**
+ * Returns the name of the class to be tested
+ *
+ * @since 1.8
+ *
+ * @return string
+ */
+ public function getClass() {
+ return 'SMW\DIConcept';
+ }
+
+ /**
+ * @see DataItemTest::constructorProvider
+ *
+ * @since 1.8
+ *
+ * @return array
+ */
+ public function constructorProvider() {
+ return [
+ [ 'Foo', '', '', '', '' ],
+ ];
+ }
+
+ /**
+ * @test DIConcept::setCacheStatus
+ * @test DIConcept::setCacheDate
+ * @test DIConcept::setCacheCount
+ * @dataProvider conceptCacheDataProvider
+ *
+ * @since 1.9
+ *
+ * @param $status
+ * @param $date
+ * @param $count
+ */
+ public function testConceptCacheSetterGetter( $status, $date, $count ) {
+
+ $reflector = new \ReflectionClass( $this->getClass() );
+ $instance = $reflector->newInstanceArgs( [ 'Foo', '', '', '', '' ] );
+
+ $instance->setCacheStatus( $status );
+ $instance->setCacheDate( $date );
+ $instance->setCacheCount( $count );
+
+ $this->assertEquals( $status, $instance->getCacheStatus() );
+ $this->assertEquals( $date, $instance->getCacheDate() );
+ $this->assertEquals( $count, $instance->getCacheCount() );
+
+ }
+
+ /**
+ * Data provider for testing concept cache setter/getter
+ *
+ * @since 1.9
+ *
+ * @return array
+ */
+ public function conceptCacheDataProvider() {
+ return [
+ [ 'empty', '', '' ],
+ [ 'full', '1358515326', '1000' ],
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIPropertyTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIPropertyTest.php
new file mode 100644
index 00000000..db82382c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIPropertyTest.php
@@ -0,0 +1,227 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\PropertyRegistry;
+use SMWDataItem as DataItem;
+
+/**
+ * @covers \SMW\DIProperty
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ * @author Nischay Nahata
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class DIPropertyTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ protected function tearDown() {
+ PropertyRegistry::clear();
+ parent::tearDown();
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testCanConstruct( $arg ) {
+
+ $this->assertInstanceOf(
+ DataItem::class,
+ new DIProperty( $arg )
+ );
+
+ $this->assertInstanceOf(
+ DIProperty::class,
+ new DIProperty( $arg )
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testSerialization( $arg ) {
+ $instance = new DIProperty( $arg );
+
+ $this->assertEquals(
+ $instance,
+ $instance->doUnserialize( $instance->getSerialization() )
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testInstanceEqualsItself( $arg ) {
+
+ $instance = new DIProperty( $arg );
+
+ $this->assertTrue(
+ $instance->equals( $instance )
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ */
+ public function testInstanceDoesNotEqualNyanData( $arg ) {
+
+ $instance = new DIProperty( $arg );
+
+ $this->assertFalse(
+ $instance->equals( new \SMWDIBlob( '~=[,,_,,]:3' ) )
+ );
+ }
+
+ public function constructorProvider() {
+ return [
+ [ 0 ],
+ [ 243.35353 ],
+ [ 'ohi there' ],
+ ];
+ }
+
+ public function testSetPropertyTypeIdOnUserDefinedProperty() {
+
+ $property = new DIProperty( 'SomeBlobProperty' );
+ $property->setPropertyTypeId( '_txt' );
+
+ $this->assertEquals( '_txt', $property->findPropertyTypeID() );
+ }
+
+ public function testSetPropertyTypeIdOnPredefinedProperty() {
+
+ $property = new DIProperty( '_MDAT' );
+ $property->setPropertyTypeId( '_dat' );
+
+ $this->assertEquals( '_dat', $property->findPropertyTypeID() );
+ }
+
+ public function testSetUnknownPropertyTypeIdThrowsException() {
+
+ $property = new DIProperty( 'SomeUnknownTypeIdProperty' );
+
+ $this->setExpectedException( '\SMW\Exception\DataTypeLookupException' );
+ $property->setPropertyTypeId( '_unknownTypeId' );
+ }
+
+ public function testSetPropertyTypeIdOnPredefinedPropertyThrowsException() {
+
+ $property = new DIProperty( '_MDAT' );
+
+ $this->setExpectedException( 'RuntimeException' );
+ $property->setPropertyTypeId( '_txt' );
+ }
+
+ public function testCorrectInversePrefixForPredefinedProperty() {
+
+ $property = new DIProperty( '_SOBJ', true );
+
+ $this->assertTrue(
+ $property->isInverse()
+ );
+
+ $label = $property->getLabel();
+
+ $this->assertEquals(
+ '-',
+ $label{0}
+ );
+ }
+
+ public function testUseInterwikiPrefix() {
+
+ $property = new DIProperty( 'Foo' );
+ $property->setInterwiki( 'bar' );
+
+ $this->assertEquals(
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY, 'bar' ),
+ $property->getDiWikiPage()
+ );
+ }
+
+ public function testCreatePropertyFromLabelThatContainsInverseMarker() {
+
+ $property = DIProperty::newFromUserLabel( '-Foo' );
+ $property->setInterwiki( 'bar' );
+
+ $this->assertTrue(
+ $property->isInverse()
+ );
+
+ $this->assertEquals(
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY, 'bar' ),
+ $property->getDiWikiPage()
+ );
+ }
+
+ public function testCreatePropertyFromLabelThatContainsLanguageMarker() {
+
+ $property = DIProperty::newFromUserLabel( '-Foo@en' );
+ $property->setInterwiki( 'bar' );
+
+ $this->assertTrue(
+ $property->isInverse()
+ );
+
+ $this->assertEquals(
+ new DIWikiPage( 'Foo', SMW_NS_PROPERTY, 'bar' ),
+ $property->getDiWikiPage()
+ );
+ }
+
+ /**
+ * @dataProvider labelProvider
+ */
+ public function testNewFromLabel( $label, $iw, $lc, $expected ) {
+
+ $property = DIProperty::newFromUserLabel( $label, $iw, $lc );
+
+ $this->assertEquals(
+ $expected,
+ $property->getKey()
+ );
+ }
+
+ public function testCanonicalRepresentation() {
+
+ $property = new DIProperty( '_MDAT' );
+
+ $this->assertEquals(
+ 'Modification date',
+ $property->getCanonicalLabel()
+ );
+
+ $this->assertEquals(
+ new DIWikiPage( 'Modification_date', SMW_NS_PROPERTY ),
+ $property->getCanonicalDiWikiPage()
+ );
+ }
+
+ public function labelProvider() {
+
+ $provider['testCreatePropertyFromLabelWithAnnotatedLangCodeToTakePrecedence'] = [
+ 'A le type@fr', '', 'es',
+ '_TYPE'
+ ];
+
+ $provider['testCreatePropertyFromLabelWithExplicitLanguageCode'] = [
+ 'Fecha de modificación', '', 'es' ,
+ '_MDAT'
+ ];
+
+ $provider['MIMEType'] = [
+ 'MIME_type', '', 'en',
+ '_MIME'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DITimeTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DITimeTest.php
new file mode 100644
index 00000000..04d732a5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DITimeTest.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMWDITime as DITime;
+
+/**
+ * @covers \SMWDITime
+ *
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DITimeTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWDITime',
+ new DITime( DITime::CM_GREGORIAN, 1970 )
+ );
+ }
+
+ public function testNewFromTimestamp() {
+
+ $instance = DITime::newFromTimestamp( '1362200400' );
+
+ $this->assertInstanceOf(
+ '\SMWDITime',
+ $instance
+ );
+ }
+
+ public function testNewFromDateTime() {
+
+ $instance = DITime::newFromDateTime(
+ new \DateTime( '2012-07-08 11:14:15.638276' )
+ );
+
+ $this->assertEquals(
+ '15.638276',
+ $instance->getSecond()
+ );
+
+ $instance = DITime::newFromDateTime(
+ new \DateTime( '1582-10-04' )
+ );
+
+ $this->assertEquals(
+ DITime::CM_JULIAN,
+ $instance->getCalendarModel()
+ );
+
+ $instance = DITime::newFromDateTime(
+ new \DateTime( '1582-10-05' )
+ );
+
+ $this->assertEquals(
+ DITime::CM_GREGORIAN,
+ $instance->getCalendarModel()
+ );
+ }
+
+ public function testDateTimeRoundTrip() {
+
+ $dateTime = new \DateTime( '2012-07-08 11:14:15.638276' );
+
+ $instance = DITime::newFromDateTime(
+ $dateTime
+ );
+
+ $this->assertEquals(
+ $dateTime,
+ $instance->asDateTime()
+ );
+ }
+
+ public function testDateTimeWithLargeMs() {
+
+ $dateTime = new \DateTime( '1300-11-02 12:03:25.888500' );
+
+ $instance = new DITime(
+ 2, 1300, 11, 02, 12, 03, 25.888499949
+ );
+
+ if ( $instance->asDateTime() != $dateTime ) {
+ $this->markTestSkipped( 'For some reason this started to fail on 5.6.19 (worked on 5.6.18)' );
+ }
+
+ $this->assertEquals(
+ $dateTime,
+ $instance->asDateTime()
+ );
+ }
+
+ public function testDateTimeWithHistoricDate() {
+
+ $dateTime = new \DateTime( '-0900-02-02 00:00:00' );
+
+ $instance = new DITime(
+ 2, -900, 02, 02
+ );
+
+ $this->assertEquals(
+ $dateTime,
+ $instance->asDateTime()
+ );
+ }
+
+ public function testDeserializationOnIncompleteFormat() {
+
+ $instance = new DITime(
+ 1, 2013, 0, 2, 0
+ );
+
+ $this->assertEquals(
+ $instance,
+ DITime::doUnserialize( '1/2013/0/2/0/' )
+ );
+ }
+
+ /**
+ * @dataProvider jdProvider
+ */
+ public function testNewFromJD( $jd, $expected ) {
+
+ $this->assertEquals(
+ DITime::doUnserialize( $expected ),
+ DITime::newFromJD( $jd )
+ );
+ }
+
+ public function testTryToDeserializeOnNonNumericElementsThrowsException() {
+
+ $this->setExpectedException( '\SMW\Exception\DataItemException' );
+ DITime::doUnserialize( '1/2013/0/2/0/foo' );
+ }
+
+ public function testTryToDeserializeOnInvalidCountOfElementsThrowsException() {
+
+ $this->setExpectedException( '\SMW\Exception\DataItemException' );
+ DITime::doUnserialize( '1' );
+ }
+
+ public function jdProvider() {
+
+ $provider[] = [
+ '2488345.500000',
+ '1/2100/10/04'
+ ];
+
+ $provider[] = [
+ '2488346.0804977',
+ '1/2100/10/4/13/55/55'
+ ];
+
+ $provider[] = [
+ '1',
+ '2/-4713/01/02/12'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIWikiPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIWikiPageTest.php
new file mode 100644
index 00000000..fa5fc026
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DIWikiPageTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIWikiPage;
+
+/**
+ * @covers \SMW\DIWikiPage
+ * @covers SMWDataItem
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group SMWDataItems
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class DIWikiPageTest extends DataItemTest {
+
+ /**
+ * @see DataItemTest::getClass
+ *
+ * @since 1.9
+ *
+ * @return string
+ */
+ public function getClass() {
+ return 'SMW\DIWikiPage';
+ }
+
+ /**
+ * @see DataItemTest::constructorProvider
+ *
+ * @since 1.9
+ *
+ * @return array
+ */
+ public function constructorProvider() {
+ return [
+ [ 'Foo', NS_MAIN, '' ],
+ [ 'Foo_Bar', NS_MAIN, '' ],
+ [ 'Foo_Bar_Baz', NS_MAIN, '', 'spam' ],
+ ];
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ */
+ public function testGetTitleAndNewFromTitleRoundrtip( DIWikiPage $di ) {
+ $newDi = DIWikiPage::newFromTitle( $di->getTitle() );
+ $this->assertTrue( $newDi->equals( $di ) );
+ }
+
+ /**
+ * @dataProvider sortKeyProvider
+ */
+ public function testSortKeyRoundtrip( $title, $sortkey, $expected ) {
+
+ $instance = new DIWikiPage( $title, NS_MAIN );
+
+ $instance->setSortKey( $sortkey );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getSortKey()
+ );
+ }
+
+ public function testDoUnserialize() {
+
+ $expected = new DIWikiPage( 'Foo', 0 , '', '' );
+
+ $this->assertEquals(
+ $expected,
+ DIWikiPage::doUnserialize( 'Foo#0##' )
+ );
+
+ $this->assertEquals(
+ $expected,
+ DIWikiPage::doUnserialize( 'Foo#0##' )
+ );
+ }
+
+ public function sortKeyProvider() {
+
+ $provider[] = [
+ 'Some_title',
+ null,
+ 'Some title'
+ ];
+
+ $provider[] = [
+ 'Some_title',
+ '',
+ 'Some title'
+ ];
+
+ $provider[] = [
+ 'Some_title',
+ 'abc',
+ 'abc'
+ ];
+
+ $provider[] = [
+ 'Some_title',
+ 'abc_def',
+ 'abc def'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BlobTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BlobTest.php
new file mode 100644
index 00000000..432d8580
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BlobTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @covers SMWDIBlob
+ * @covers SMWDataItem
+ *
+ * @file
+ * @since 1.8
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group SMWDataItems
+ *
+ * @author Nischay Nahata
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class DIBlobTest extends DataItemTest {
+
+ /**
+ * @see DataItemTest::getClass
+ *
+ * @since 1.8
+ *
+ * @return string
+ */
+ public function getClass() {
+ return '\SMWDIBlob';
+ }
+
+ /**
+ * @see DataItemTest::constructorProvider
+ *
+ * @since 1.8
+ *
+ * @return array
+ */
+ public function constructorProvider() {
+ return [
+ [ 'I love Semantic MediaWiki' ],
+ [ 'It is open source' ],
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BoolTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BoolTest.php
new file mode 100644
index 00000000..fee4ad55
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_BoolTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @covers SMWDIBoolean
+ * @covers SMWDataItem
+ *
+ * @file
+ * @since 1.8
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group SMWDataItems
+ *
+ * @author Nischay Nahata
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SMWDIBooleanTest extends DataItemTest {
+
+ /**
+ * @see DataItemTest::getClass
+ *
+ * @since 1.8
+ *
+ * @return string
+ */
+ public function getClass() {
+ return '\SMWDIBoolean';
+ }
+
+ /**
+ * @see DataItemTest::constructorProvider
+ *
+ * @since 1.8
+ *
+ * @return array
+ */
+ public function constructorProvider() {
+ return [
+ [ false ],
+ [ true ],
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_GeoCoordTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_GeoCoordTest.php
new file mode 100644
index 00000000..5beeca4f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_GeoCoordTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Exception\DataItemException;
+
+/**
+ * @covers SMWDIGeoCoord
+ * @covers SMWDataItem
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SMWDIGeoCoordTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ public function testConstructorWithArrayArgumentForm() {
+ $coordinate = new \SMWDIGeoCoord( [ 'lat' => 13.37, 'lon' => 42.42 ] );
+
+ $this->assertSame( 13.37, $coordinate->getLatitude() );
+ $this->assertSame( 42.42, $coordinate->getLongitude() );
+ }
+
+ public function testConstructorWithMultipleArgumentsForm() {
+ $coordinate = new \SMWDIGeoCoord( 13.37, 42.42 );
+
+ $this->assertSame( 13.37, $coordinate->getLatitude() );
+ $this->assertSame( 42.42, $coordinate->getLongitude() );
+ }
+
+ public function testWhenConstructingWithIntegers_gettersReturnFloats() {
+ $coordinate = new \SMWDIGeoCoord( 13, 42 );
+
+ $this->assertSame( 13.0, $coordinate->getLatitude() );
+ $this->assertSame( 42.0, $coordinate->getLongitude() );
+ }
+
+ public function testWhenOnlyProvidingLatitudeArgument_constructorThrowsException() {
+ $this->setExpectedException( DataItemException::class );
+ new \SMWDIGeoCoord( 13 );
+ }
+
+ public function testWhenProvidingNonNumericalArgument_constructorThrowsException() {
+ $this->setExpectedException( DataItemException::class );
+ new \SMWDIGeoCoord( 13, null );
+ }
+
+ public function testWhenProvidingArrayWithNonNumericalArgument_constructorThrowsException() {
+ $this->setExpectedException( DataItemException::class );
+ new \SMWDIGeoCoord( [ 'lat' => null, 'lon' => 42.42 ] );
+ }
+
+ public function testObjectEqualsItself() {
+ $coordinate = new \SMWDIGeoCoord( 13, 42 );
+ $this->assertTrue( $coordinate->equals( $coordinate ) );
+ }
+
+ public function testObjectEqualsDifferentInstancesWithEqualValues() {
+ $coordinate = new \SMWDIGeoCoord( 13, 42 );
+ $this->assertTrue( $coordinate->equals( new \SMWDIGeoCoord( 13.0, 42.0 ) ) );
+ }
+
+ public function testObjectDoesNotEqualInstancesWithDifferentValues() {
+ $coordinate = new \SMWDIGeoCoord( 13, 42 );
+ $this->assertFalse( $coordinate->equals( new \SMWDIGeoCoord( 1, 2 ) ) );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_NumberTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_NumberTest.php
new file mode 100644
index 00000000..807414c3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DI_NumberTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace SMW\Tests;
+
+/**
+ * @covers SMWDINumber
+ * @covers SMWDataItem
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group SMWDataItems
+ * @group SMWDINumberTest
+ *
+ * @author Nischay Nahata
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+class SMWDINumberTest extends DataItemTest {
+
+ /**
+ * @see DataItemTest::getClass
+ *
+ * @since 1.8
+ *
+ * @return string
+ */
+ public function getClass() {
+ return '\SMWDINumber';
+ }
+
+ /**
+ * @see DataItemTest::constructorProvider
+ *
+ * @since 1.8
+ *
+ * @return array
+ */
+ public function constructorProvider() {
+ return [
+ [ 0 ],
+ [ 243.35353 ],
+ ];
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DataItemTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DataItemTest.php
new file mode 100644
index 00000000..a41629b2
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/dataitems/DataItemTest.php
@@ -0,0 +1,110 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMWDataItem;
+
+/**
+ * Base class for SMW\DataItem tests.
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group SMWDataItems
+ *
+ * @licence GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+abstract class DataItemTest extends MwDBaseUnitTestCase {
+
+ /**
+ * Returns the name of the \SMW\DataItem deriving class this test tests.
+ *
+ * @since 1.8
+ *
+ * @return string
+ */
+ public abstract function getClass();
+
+ /**
+ * @since 1.8
+ *
+ * @return array
+ */
+ public abstract function constructorProvider();
+
+ /**
+ * Creates and returns a new instance of the data item.
+ *
+ * @since 1.8
+ *
+ * @return SMWDataItem
+ */
+ public function newInstance() {
+ $reflector = new \ReflectionClass( $this->getClass() );
+ $args = func_get_args();
+ $instance = $reflector->newInstanceArgs( $args );
+ return $instance;
+ }
+
+ /**
+ * @since 1.8
+ *
+ * @return array
+ */
+ public function instanceProvider() {
+ $phpFails = [ $this, 'newInstance' ];
+
+ return array_map(
+ function( array $args ) use ( $phpFails ) {
+ return [ call_user_func_array( $phpFails, $args ) ];
+ },
+ $this->constructorProvider()
+ );
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ *
+ * @since 1.8
+ */
+ public function testConstructor() {
+ $dataItem = call_user_func_array(
+ [ $this, 'newInstance' ],
+ func_get_args()
+ );
+
+ $this->assertInstanceOf( '\SMWDataItem', $dataItem );
+ $this->assertInstanceOf( $this->getClass(), $dataItem );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ *
+ * @since 1.8
+ *
+ * @param \SMWDataItem $dataItem
+ */
+ public function testSerialization( \SMWDataItem $dataItem ) {
+ $class = $this->getClass();
+
+ $this->assertEquals(
+ $dataItem,
+ $class::doUnserialize( $dataItem->getSerialization() )
+ );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ */
+ public function testInstanceEqualsItself( SMWDataItem $di ) {
+ $this->assertTrue( $di->equals( $di ) );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ */
+ public function testInstanceDoesNotEqualNyanData( SMWDataItem $di ) {
+ $this->assertFalse( $di->equals( new \SMWDIBlob( '~=[,,_,,]:3' ) ) );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExpDataTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExpDataTest.php
new file mode 100644
index 00000000..42120707
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExpDataTest.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace SMW\Tests\Exporter;
+
+use SMW\Exporter\Element\ExpLiteral;
+use SMW\Exporter\Element\ExpNsResource;
+use SMWExpData as ExpData;
+
+/**
+ * @covers \SMWExpData
+ *
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ */
+class ExpDataTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstructor() {
+
+ $expNsResource = $this->getMockBuilder( '\SMW\Exporter\Element\ExpNsResource' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->assertInstanceOf(
+ '\SMWExpData',
+ new ExpData( $expNsResource )
+ );
+ }
+
+ /**
+ * @dataProvider expDataHashProvider
+ */
+ public function testGetHash( $expData, $expected ) {
+
+ $this->assertEquals(
+ $expected,
+ $expData->getHash()
+ );
+ }
+
+ public function expDataHashProvider() {
+
+ #0
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $provider[] = [
+ $expData,
+ '4dc04c87e9660854a5609ff132175fd5'
+ ];
+
+ #1
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $provider[] = [
+ $expData,
+ '5702e5e8c6145aaf8d89840a4a3b18c2'
+ ];
+
+ #2
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Bar', 'Foo' )
+ );
+
+ $provider[] = [
+ $expData,
+ '13edcedd007979f5638fbc958f0cdaf8'
+ ];
+
+ #3 Same as 2 but different sorting/same hash
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Bar', 'Foo' )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $provider[] = [
+ $expData,
+ '13edcedd007979f5638fbc958f0cdaf8'
+ ];
+
+ #4 Nesting
+ $expDataLevel2 = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expDataLevel2->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $expData = new ExpData(
+ new ExpNsResource( 'Foo', 'Bar', 'Mo', null )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ new ExpLiteral( 'Foo', 'Bar' )
+ );
+
+ $expData->addPropertyObjectValue(
+ new ExpNsResource( 'Li', 'La', 'Lu', null ),
+ $expDataLevel2
+ );
+
+ $provider[] = [
+ $expData,
+ 'e684e7640a201d2d33e035aaa866c1ac'
+ ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExportSemanticDataTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExportSemanticDataTest.php
new file mode 100644
index 00000000..5e49ca3a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/ExportSemanticDataTest.php
@@ -0,0 +1,344 @@
+<?php
+
+namespace SMW\Tests\Export;
+
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Exporter\Escaper;
+use SMW\Subobject;
+use SMW\Tests\Utils\Fixtures\FixturesProvider;
+use SMW\Tests\Utils\SemanticDataFactory;
+use SMW\Tests\Utils\Validators\ExportDataValidator;
+use SMWExpNsResource as ExpNsResource;
+use SMWExporter as Exporter;
+
+/**
+ * @covers \SMWExporter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.0
+ *
+ * @author mwjames
+ */
+class ExportSemanticDataTest extends \PHPUnit_Framework_TestCase {
+
+ private $semanticDataFactory;
+ private $dataValueFactory;
+ private $exportDataValidator;
+ private $fixturesProvider;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->semanticDataFactory = new SemanticDataFactory();
+ $this->exportDataValidator = new ExportDataValidator();
+
+ $this->fixturesProvider = new FixturesProvider();
+ }
+
+ public function testExportRedirect() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $redirectProperty = new DIProperty( '_REDI' );
+ $redirectTarget = new DIWikiPage( 'FooRedirectTarget', NS_MAIN, '' );
+
+ $semanticData->addPropertyObjectValue(
+ $redirectProperty,
+ DIWikiPage::newFromTitle( $redirectTarget->getTitle(), '__red' )
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData( $semanticData );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( Exporter::getInstance()->getSpecialNsResource( 'swivt', 'redirectsTo' ) )
+ );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( Exporter::getInstance()->getSpecialNsResource( 'owl', 'sameAs' ) )
+ );
+
+ $expectedResourceElement = new ExpNsResource(
+ 'FooRedirectTarget',
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'wiki',
+ $redirectTarget
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsResource(
+ $expectedResourceElement,
+ Exporter::getInstance()->getSpecialNsResource( 'owl', 'sameAs' ),
+ $exportData
+ );
+ }
+
+ public function testExportPageWithNumericProperty() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $property = new DIProperty( '123' );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( '345', NS_MAIN )
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData( $semanticData );
+
+ $expectedProperty = new ExpNsResource(
+ Escaper::encodePage( $property->getDiWikiPage() ),
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'wiki',
+ new DIWikiPage( '123', SMW_NS_PROPERTY )
+ );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( $expectedProperty )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsProperty(
+ $expectedProperty,
+ $exportData
+ );
+
+ $expectedResourceElement = new ExpNsResource(
+ '345',
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'wiki',
+ new DIWikiPage( '345', NS_MAIN )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsResource(
+ $expectedResourceElement,
+ $expectedProperty,
+ $exportData
+ );
+ }
+
+ public function testExportPageWithNonNumericProperty() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $property = new DIProperty( 'A123' );
+
+ $semanticData->addPropertyObjectValue(
+ $property,
+ new DIWikiPage( '345', NS_MAIN )
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData( $semanticData );
+
+ $expectedProperty = new ExpNsResource(
+ 'A123',
+ Exporter::getInstance()->getNamespaceUri( 'property' ),
+ 'property',
+ new DIWikiPage( 'A123', SMW_NS_PROPERTY )
+ );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( $expectedProperty )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsProperty(
+ $expectedProperty,
+ $exportData
+ );
+
+ $expectedResource = new ExpNsResource(
+ '345',
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'wiki',
+ new DIWikiPage( '345', NS_MAIN )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsResource(
+ $expectedResource,
+ $expectedProperty,
+ $exportData
+ );
+ }
+
+ public function testExportSubproperty() {
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( new DIWikiPage( 'SomeSubproperty', SMW_NS_PROPERTY ) )
+ ->newEmptySemanticData();
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByProperty( new DIProperty( '_SUBP' ), 'SomeTopProperty' )
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData( $semanticData );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( Exporter::getInstance()->getSpecialNsResource( 'rdfs', 'subPropertyOf' ) )
+ );
+
+ $expectedResourceElement = new ExpNsResource(
+ 'SomeTopProperty',
+ Exporter::getInstance()->getNamespaceUri( 'property' ),
+ 'property',
+ new DIWikiPage( 'SomeTopProperty', SMW_NS_PROPERTY )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsResource(
+ $expectedResourceElement,
+ Exporter::getInstance()->getSpecialNsResource( 'rdfs', 'subPropertyOf' ),
+ $exportData
+ );
+ }
+
+ public function testExportCategory() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByProperty( new DIProperty( '_INST' ), 'SomeCategory' )
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData( $semanticData );
+
+ $this->assertCount(
+ 2,
+ $exportData->getValues( Exporter::getInstance()->getSpecialNsResource( 'rdf', 'type' ) )
+ );
+
+ $expectedResourceElement = new ExpNsResource(
+ 'SomeCategory',
+ Exporter::getInstance()->getNamespaceUri( 'category' ),
+ 'category',
+ new DIWikiPage( 'SomeCategory', NS_CATEGORY )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsResource(
+ $expectedResourceElement,
+ Exporter::getInstance()->getSpecialNsResource( 'rdf', 'type' ),
+ $exportData
+ );
+ }
+
+ public function testExportSubcategory() {
+
+ $semanticData = $this->semanticDataFactory
+ ->setSubject( new DIWikiPage( 'SomeSubcategory', NS_CATEGORY ) )
+ ->newEmptySemanticData();
+
+ $semanticData->addDataValue(
+ $this->dataValueFactory->newDataValueByProperty( new DIProperty( '_SUBC' ), 'SomeTopCategory' )
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData( $semanticData );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( Exporter::getInstance()->getSpecialNsResource( 'rdfs', 'subClassOf' ) )
+ );
+
+ $expectedResourceElement = new ExpNsResource(
+ 'SomeTopCategory',
+ Exporter::getInstance()->getNamespaceUri( 'category' ),
+ 'category',
+ new DIWikiPage( 'SomeTopCategory', NS_CATEGORY )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsResource(
+ $expectedResourceElement,
+ Exporter::getInstance()->getSpecialNsResource( 'rdfs', 'subClassOf' ),
+ $exportData
+ );
+ }
+
+ public function testExportSubobject() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $subobject = new Subobject( $semanticData->getSubject()->getTitle() );
+ $subobject->setEmptyContainerForId( 'Foo' );
+
+ $semanticData->addPropertyObjectValue(
+ $subobject->getProperty(),
+ $subobject->getContainer()
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData( $semanticData );
+
+ $expectedProperty = new ExpNsResource(
+ $this->transformPropertyLabelToAuxiliary( $subobject->getProperty() ),
+ Exporter::getInstance()->getNamespaceUri( 'property' ),
+ 'property',
+ new DIWikiPage( 'Has_subobject', SMW_NS_PROPERTY )
+ );
+
+ $this->assertTrue(
+ Exporter::getInstance()->hasHelperExpElement( $subobject->getProperty() )
+ );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( $expectedProperty )
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsProperty(
+ $expectedProperty,
+ $exportData
+ );
+
+ $expectedResource = new ExpNsResource(
+ Escaper::encodePage( $subobject->getSemanticData()->getSubject() ) . '-23' . 'Foo',
+ Exporter::getInstance()->getNamespaceUri( 'wiki' ),
+ 'wiki',
+ $subobject->getSemanticData()->getSubject()
+ );
+
+ $this->exportDataValidator->assertThatExportDataContainsResource(
+ $expectedResource,
+ $expectedProperty,
+ $exportData
+ );
+ }
+
+ public function testExportSubSemanticData() {
+
+ $semanticData = $this->semanticDataFactory->newEmptySemanticData( __METHOD__ );
+
+ $factsheet = $this->fixturesProvider->getFactsheet( 'berlin' );
+ $factsheet->setTargetSubject( $semanticData->getSubject() );
+
+ $demographicsSubobject = $factsheet->getDemographics();
+
+ $semanticData->addPropertyObjectValue(
+ $demographicsSubobject->getProperty(),
+ $demographicsSubobject->getContainer()
+ );
+
+ $exportData = Exporter::getInstance()->makeExportData(
+ $semanticData->findSubSemanticData( $demographicsSubobject->getSubobjectId() )
+ );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( Exporter::getInstance()->getSpecialPropertyResource( '_SKEY' ) )
+ );
+
+ $this->assertCount(
+ 1,
+ $exportData->getValues( Exporter::getInstance()->getSpecialNsResource( 'swivt', 'wikiNamespace' ) )
+ );
+ }
+
+ private function transformPropertyLabelToAuxiliary( DIProperty $property ) {
+ return str_replace( ' ', '_', $property->getLabel() );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/SMWExporterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/SMWExporterTest.php
new file mode 100644
index 00000000..ef5cd36b
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/export/SMWExporterTest.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIWikiPage;
+use SMWDataItem as DataItem;
+use SMWDIBlob as DIBlob;
+use SMWDIBoolean as DIBoolean;
+use SMWDIConcept as DIConcept;
+use SMWDINumber as DINumber;
+use SMWExporter as Exporter;
+use SMWExpResource as ExpResource;
+
+/**
+ * @covers \SMWExporter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SMWExporterTest extends \PHPUnit_Framework_TestCase {
+
+ // @see #795
+ public function testExportDataForPropertyPage() {
+
+ $propertyPage = new DIWikiPage( 'Foo', SMW_NS_PROPERTY );
+
+ $expData = Exporter::getInstance()->makeExportDataForSubject( $propertyPage );
+
+ $this->assertInstanceOf(
+ '\SMWExpData',
+ $expData
+ );
+
+ $this->assertInstanceOf(
+ '\SMWExpNsResource',
+ $expData->getSubject()
+ );
+ }
+
+ /**
+ * @dataProvider dataItemExpElementProvider
+ */
+ public function testGetDataItemExpElement( DataItem $dataItem, $instance ) {
+
+ if ( $instance === null ) {
+ return $this->assertNull( Exporter::getInstance()->getDataItemExpElement( $dataItem ) );
+ }
+
+ $this->assertInstanceOf(
+ $instance,
+ Exporter::getInstance()->getDataItemExpElement( $dataItem )
+ );
+ }
+
+ /**
+ * @dataProvider uriDataItemProvider
+ * #378
+ */
+ public function testFindDataItemForExpElement( $uri, $expectedDataItem ) {
+
+ $uri = Exporter::getInstance()->getNamespaceUri( 'wiki' ) . $uri;
+
+ $this->assertEquals(
+ $expectedDataItem,
+ Exporter::getInstance()->findDataItemForExpElement( new ExpResource( $uri ) )
+ );
+ }
+
+ public function dataItemExpElementProvider() {
+
+ // #0 (bug 56643)
+ $provider[] = [ new DINumber( 9001 ), 'SMWExpElement' ];
+
+ $provider[] = [ new DIBlob( 'foo' ), 'SMWExpElement' ];
+ $provider[] = [ new DIBoolean( true ), 'SMWExpElement' ];
+
+ $provider[] = [ new DIConcept( 'Foo', '', '', '', '' ), 'SMWExpData' ];
+
+ return $provider;
+ }
+
+ public function uriDataItemProvider() {
+
+ $provider[] = [ 'Foo', new DIWikiPage( 'Foo', NS_MAIN, '', '' ) ];
+ $provider[] = [ 'Foo#Bar', new DIWikiPage( 'Foo', NS_MAIN, '', 'Bar' ) ];
+ $provider[] = [ 'Foo#Bar#Oooo', new DIWikiPage( 'Foo', NS_MAIN, '', 'Bar#Oooo' ) ];
+ $provider[] = [ 'Property:Foo', new DIWikiPage( 'Foo', SMW_NS_PROPERTY, '', '' ) ];
+ $provider[] = [ 'Concept:Foo', new DIWikiPage( 'Foo', SMW_NS_CONCEPT, '', '' ) ];
+ $provider[] = [ 'Unknown:Foo', new DIWikiPage( 'Unknown:Foo', NS_MAIN, '', '' ) ];
+ $provider[] = [ 'Unknown:Foo#Bar', new DIWikiPage( 'Unknown:Foo', NS_MAIN, '', 'Bar' ) ];
+ $provider[] = [ 'Property:Foo#Bar', new DIWikiPage( 'Foo', SMW_NS_PROPERTY, '', 'Bar' ) ];
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/formatters/MessageFormatterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/formatters/MessageFormatterTest.php
new file mode 100644
index 00000000..02dfdef1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/formatters/MessageFormatterTest.php
@@ -0,0 +1,282 @@
+<?php
+
+namespace SMW\Test;
+
+use Message;
+use ReflectionClass;
+use SMW\MessageFormatter;
+
+/**
+ * Tests for the MessageFormatter class
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * @covers \SMW\MessageFormatter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class MessageFormatterTest extends SemanticMediaWikiTestCase {
+
+ /**
+ * Returns the name of the class to be tested
+ *
+ * @return string
+ */
+ public function getClass() {
+ return '\SMW\MessageFormatter';
+ }
+
+ /**
+ * Helper method that returns an MessageFormatter instance
+ *
+ * @since 1.9
+ *
+ * @return MessageFormatter
+ */
+ private function getInstance() {
+ return new MessageFormatter( $this->getLanguage() );
+ }
+
+ /**
+ * @test MessageFormatter::__construct
+ * @dataProvider getDataProvider
+ *
+ * @since 1.9
+ */
+ public function testConstructor() {
+ $instance = $this->getInstance();
+ $this->assertInstanceOf( $this->getClass(), $instance );
+ }
+
+ /**
+ * @test MessageFormatter::newFromArray
+ * @test MessageFormatter::setType
+ * @test MessageFormatter::getHtml
+ * @dataProvider getDataProvider
+ *
+ * @since 1.9
+ *
+ * @param array $messages
+ */
+ public function testNewFromArray( array $messages ) {
+ $instance = MessageFormatter::newFromArray(
+ $this->getLanguage(),
+ $messages
+ );
+
+ $instance->setType( 'error' );
+ $this->assertInternalType( 'string', $instance->getHtml() );
+
+ $instance->setType( 'warning' );
+ $this->assertInternalType( 'string', $instance->getHtml() );
+
+ $instance->setType( 'info' );
+ $this->assertInternalType( 'string', $instance->getHtml() );
+
+ }
+
+ /**
+ * @test MessageFormatter::addFromKey
+ * @test MessageFormatter::getMessages
+ *
+ * @since 1.9
+ */
+ public function testAddFromKey() {
+ $instance = $this->getInstance();
+ $param = '1001';
+
+ $instance->addFromKey( 'Foo', $param )
+ ->addFromKey( 'Bar', $param )
+ ->addFromKey( 'Foo', $param );
+
+ $messages = $instance->getMessages();
+
+ // Returns count of existing with duplicates, elimination is
+ // applied only during output (getHtml/getPlain)
+ $this->assertCount( 3, $messages );
+
+ foreach ( $messages as $msg ) {
+ $this->assertInstanceOf( '\Message', $msg );
+
+ // getParams() only got added in MW 1.21
+ if ( method_exists( $msg, 'getParams' ) ) {
+ foreach ( $msg->getParams() as $result ) {
+ $this->assertEquals( $param, $result );
+ }
+ }
+ }
+ }
+
+ /**
+ * @test MessageFormatter::setLanguage
+ * @test MessageFormatter::getPlain
+ *
+ * @since 1.9
+ */
+ public function testSetLanguage() {
+ $key = 'properties';
+ $msg = new Message( $key );
+ $instance = $this->getInstance();
+
+ $instance->addFromKey( $key );
+ $instance->setLanguage( $this->getLanguage( 'zh-tw' ) );
+
+ $this->assertEquals(
+ $msg->inLanguage( $this->getLanguage( 'zh-tw' ) )->text(),
+ $instance->getPlain()
+ );
+
+ $instance->clear();
+ $this->assertEmpty( $instance->getPlain() );
+
+ }
+
+ /**
+ * @test MessageFormatter::format
+ * @dataProvider getDataProvider
+ *
+ * @since 1.9
+ *
+ * @param array $messages
+ * @param integer $count
+ */
+ public function testFormat( array $messages, $count ) {
+ $instance = $this->getInstance();
+ $instance->addFromArray( $messages );
+
+ // Access protected method
+ $reflection = new ReflectionClass( $this->getClass() );
+ $method = $reflection->getMethod( 'doFormat' );
+ $method->setAccessible( true );
+
+ // Test array normalization and deletion of duplicates
+ $result = $method->invoke( $instance, $instance->getMessages() );
+ $this->assertCount( $count, $result );
+
+ }
+
+ /**
+ * @test MessageFormatter::getHtml
+ * @dataProvider getDataProvider
+ *
+ * @since 1.9
+ *
+ * @param array $messages
+ */
+ public function testGetHtml( array $messages ) {
+ $instance = $this->getInstance();
+ $instance->addFromArray( $messages );
+
+ $this->assertInternalType( 'string', $instance->getHtml() );
+ }
+
+ /**
+ * @test MessageFormatter::getPlain
+ * @dataProvider getDataProvider
+ *
+ * @since 1.9
+ *
+ * @param array $messages
+ */
+ public function testGetPlain( array $messages ) {
+ $instance = $this->getInstance();
+ $instance->addFromArray( $messages );
+
+ $this->assertInternalType( 'string', $instance->getPlain() );
+ }
+
+ /**
+ * @test MessageFormatter::escape
+ * @test MessageFormatter::getPlain
+ *
+ * @since 1.9
+ */
+ public function testEscapedUnescaped() {
+ $instance = $this->getInstance();
+ $instance->addFromArray( [ '<Foo>' ] );
+
+ $this->assertEquals( '&lt;Foo&gt;', $instance->escape( true )->getPlain() );
+ $this->assertEquals( '<Foo>', $instance->escape( false )->getPlain() );
+
+ }
+
+ /**
+ * Message from different sources could have different depth therefore
+ * objects need to be resolved recursively in order to ensure a 1-n array
+ *
+ */
+ public function getDataProvider() {
+ return [
+
+ // #0 Empty array
+ [ [], 0 ],
+
+ // #1 Simple string elements 5 elements (one duplicate) = 4
+ [
+ [
+ 'Foo', 'Bar', [ 'FooBar', [ 'barFoo', 'Foo' ] ]
+ ],
+ 4
+ ],
+
+ // #2 A duplicate Message object = 1
+ [
+ [
+ new Message( 'smw_iq_disabled' ),
+ new Message( 'smw_iq_disabled' )
+ ],
+ 1
+ ],
+
+ // #3 Different Message objects
+ [
+ [
+ new Message( 'smw_iq_disabled' ),
+ new Message( 'smw_multiple_concepts' )
+ ],
+ 2
+ ],
+
+ // #4 Invoked MessageFormatter object (recursive test)
+ [
+ [
+ new Message( 'smw_iq_disabled' ),
+ [ new Message( 'smw_iq_disabled' ),
+ new Message( 'smw_multiple_concepts' )
+ ]
+ ],
+ 2
+ ],
+
+ // #5 Combine different objects (recursive test) containing 7 messages
+ // where two of them are duplicates resulting in 5 objects
+ [
+ [
+ new Message( 'smw_iq_disabled' ),
+ new Message( 'smw_multiple_concepts' ),
+ [
+ new Message( 'smw_iq_disabled' ),
+ 'Foo'
+ ],
+ [
+ [
+ new Message( 'smw_no_concept_namespace' ),
+ new Message( 'foo' ),
+ 'Foo'
+ ]
+ ]
+ ],
+ 5
+ ],
+ ];
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/PropertiesQueryPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/PropertiesQueryPageTest.php
new file mode 100644
index 00000000..eeeaebc9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/PropertiesQueryPageTest.php
@@ -0,0 +1,188 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\ArrayAccessor;
+use SMW\DataItemFactory;
+use SMW\PropertiesQueryPage;
+use SMW\Settings;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\PropertiesQueryPage
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class PropertiesQueryPageTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $skin;
+ private $settings;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->settings = Settings::newFromArray( [
+ 'smwgPDefaultType' => '_wpg',
+ 'smwgPropertyLowUsageThreshold' => 5,
+ 'smwgPropertyZeroCountDisplay' => true
+ ] );
+
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\PropertiesQueryPage',
+ new PropertiesQueryPage( $this->store, $this->settings )
+ );
+ }
+
+ public function testFormatResultDIError() {
+
+ $error = $this->dataItemFactory->newDIError( 'Foo');
+
+ $instance = new PropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $error, null ]
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $result
+ );
+
+ $this->assertContains(
+ 'Foo',
+ $result
+ );
+ }
+
+ public function testInvalidResultThrowsException() {
+
+ $instance = new PropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $this->setExpectedException( '\SMW\Exception\PropertyNotFoundException' );
+ $instance->formatResult( $this->skin, null );
+ }
+
+ public function testFormatPropertyItemOnUserDefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new PropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $property, 42 ]
+ );
+
+ $this->assertContains(
+ 'Foo',
+ $result
+ );
+ }
+
+ public function testFormatPropertyItemOnPredefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_MDAT' );
+
+ $instance = new PropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $property, 42 ]
+ );
+
+ $this->assertContains(
+ '42',
+ $result
+ );
+ }
+
+ public function testFormatPropertyItemZeroDisplay() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $this->settings->set(
+ 'smwgPropertyZeroCountDisplay',
+ false
+ );
+
+ $instance = new PropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $property, 0 ]
+ );
+
+ $this->assertEmpty(
+ $result
+ );
+ }
+
+ public function testFormatPropertyItemLowUsageThreshold() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+ $count = 42;
+
+ $this->settings->set(
+ 'smwgPropertyLowUsageThreshold',
+ $count + 1
+ );
+
+ $this->settings->set(
+ 'smwgPDefaultType',
+ '_wpg'
+ );
+
+ $instance = new PropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $property, $count ]
+ );
+
+ $this->assertContains(
+ '42',
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/QueryPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/QueryPageTest.php
new file mode 100644
index 00000000..544f18e7
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/QueryPageTest.php
@@ -0,0 +1,140 @@
+<?php
+
+namespace SMW\Test;
+
+use ReflectionClass;
+use SMW\Tests\Utils\Mock\MockSuperUser;
+use Title;
+
+/**
+ * @covers \SMW\QueryPage
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class QueryPageTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * Helper method that returns a QueryPage object
+ *
+ * @since 1.9
+ *
+ * @param $result
+ *
+ * @return QueryPage
+ */
+ private function newInstance( $search = '' ) {
+
+ $queryPage = $this->getMockBuilder( '\SMW\QueryPage' )
+ ->setMethods( [ 'getResults', 'formatResult' ] )
+ ->getMock();
+
+ $context = $this->newContext( [ 'property' => $search ] );
+ $context->setTitle( Title::newFromText( __METHOD__ ) );
+
+ $queryPage->setContext( $context );
+
+ return $queryPage;
+ }
+
+ /**
+ * @test QueryPage::__construct
+ *
+ * @since 1.9
+ */
+ public function testConstructor() {
+ $this->assertInstanceOf( '\SMW\QueryPage', $this->newInstance() );
+ }
+
+ /**
+ * @test QueryPage::linkParameters
+ * @dataProvider linkParametersDataProvider
+ *
+ * @since 1.9
+ *
+ * @param $test
+ * @param $expected
+ */
+ public function testLinkParameters( $test, $expected ) {
+
+ $search = __METHOD__;
+ $result = $this->newInstance( $test )->linkParameters();
+
+ $this->assertInternalType( 'array', $result );
+ $this->assertEquals( $expected, $result );
+
+ }
+
+ /**
+ * @test QueryPage::getSearchForm
+ *
+ * @since 1.9
+ */
+ public function testGetSearchForm() {
+
+ $search = __METHOD__;
+ $instance = $this->newInstance();
+
+ $reflector = new ReflectionClass( '\SMW\QueryPage' );
+ $selectOptions = $reflector->getProperty( 'selectOptions' );
+ $selectOptions->setAccessible( true );
+ $selectOptions->setValue( $instance, [
+ 'offset' => 1,
+ 'limit' => 2,
+ 'end' => 5,
+ 'count' => 4
+ ] );
+
+ $result = $instance->getSearchForm( $search );
+
+ $matcher = [
+ 'tag' => 'form',
+ 'descendant' => [
+ 'tag' => 'input',
+ 'attributes' => [ 'name' => 'property', 'value' => $search ]
+ ]
+ ];
+
+ $this->assertInternalType( 'string', $result );
+
+ // https://github.com/sebastianbergmann/phpunit/issues/1380
+ // $this->assertTag( $matcher, $result );
+ $this->assertContains( $search, $result );
+ }
+
+ /**
+ * Provides sample data to be tested
+ *
+ * @return array
+ */
+ public function linkParametersDataProvider() {
+ $param = __METHOD__;
+
+ return [
+ [ '' , [] ],
+ [ null , [] ],
+ [ $param , [ 'property' => $param ] ],
+ [ "[{$param}]" , [ 'property' => "[{$param}]" ] ],
+ [ "[&{$param}...]" , [ 'property' => "[&{$param}...]" ] ]
+ ];
+ }
+
+ private function newContext( $request = [] ) {
+
+ $context = new \RequestContext();
+
+ if ( $request instanceof \WebRequest ) {
+ $context->setRequest( $request );
+ } else {
+ $context->setRequest( new \FauxRequest( $request, true ) );
+ }
+
+ $context->setUser( new MockSuperUser() );
+
+ return $context;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/UnusedPropertiesQueryPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/UnusedPropertiesQueryPageTest.php
new file mode 100644
index 00000000..5301f120
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/UnusedPropertiesQueryPageTest.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\DataItemFactory;
+use SMW\Settings;
+use SMW\Tests\TestEnvironment;
+use SMW\UnusedPropertiesQueryPage;
+use SMW\Tests\PHPUnitCompat;
+
+/**
+ * @covers \SMW\UnusedPropertiesQueryPage
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class UnusedPropertiesQueryPageTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ private $store;
+ private $skin;
+ private $settings;
+ private $dataItemFactory;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container = $this->getMockBuilder( '\Onoi\BlobStore\Container' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $blobStore = $this->getMockBuilder( '\Onoi\BlobStore\BlobStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $blobStore->expects( $this->any() )
+ ->method( 'read' )
+ ->will( $this->returnValue( $container ) );
+
+ $cachedPropertyValuesPrefetcher = $this->getMockBuilder( '\SMW\CachedPropertyValuesPrefetcher' )
+ ->setConstructorArgs( [ $this->store, $blobStore ] )
+ ->setMethods( null )
+ ->getMock();
+
+ $this->testEnvironment->registerObject( 'CachedPropertyValuesPrefetcher', $cachedPropertyValuesPrefetcher );
+
+ $this->settings = Settings::newFromArray( [] );
+
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ protected function tearDown() {
+ $this->testEnvironment->tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\UnusedPropertiesQueryPage',
+ new UnusedPropertiesQueryPage( $this->store, $this->settings )
+ );
+ }
+
+ public function testFormatResultDIError() {
+
+ $error = $this->dataItemFactory->newDIError( 'Foo');
+
+ $instance = new UnusedPropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ $error
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $result
+ );
+
+ $this->assertContains(
+ 'Foo',
+ $result
+ );
+ }
+
+ public function testInvalidResultThrowsException() {
+
+ $instance = new UnusedPropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $this->setExpectedException( '\SMW\Exception\PropertyNotFoundException' );
+ $instance->formatResult( $this->skin, null );
+ }
+
+ public function testFormatPropertyItemOnUserDefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new UnusedPropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ $property
+ );
+
+ $this->assertContains(
+ 'Foo',
+ $result
+ );
+ }
+
+ public function testFormatPropertyItemOnPredefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_MDAT' );
+
+ $instance = new UnusedPropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ $property
+ );
+
+ $this->assertContains(
+ 'Help:Special_properties',
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/WantedPropertiesQueryPageTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/WantedPropertiesQueryPageTest.php
new file mode 100644
index 00000000..a39121cc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/querypages/WantedPropertiesQueryPageTest.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\DataItemFactory;
+use SMW\Settings;
+use SMW\WantedPropertiesQueryPage;
+
+/**
+ * @covers \SMW\WantedPropertiesQueryPage
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class WantedPropertiesQueryPageTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $skin;
+ private $settings;
+ private $dataItemFactory;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->skin = $this->getMockBuilder( '\Skin' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->settings = Settings::newFromArray( [] );
+
+ $this->dataItemFactory = new DataItemFactory();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\WantedPropertiesQueryPage',
+ new WantedPropertiesQueryPage( $this->store, $this->settings )
+ );
+ }
+
+ public function testFormatResultDIError() {
+
+ $error = $this->dataItemFactory->newDIError( 'Foo');
+
+ $instance = new WantedPropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $error, null ]
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $result
+ );
+
+ $this->assertEmpty(
+ $result
+ );
+ }
+
+ public function testFormatPropertyItemOnUserDefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( 'Foo' );
+
+ $instance = new WantedPropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $property, 42 ]
+ );
+
+ $this->assertContains(
+ 'Foo',
+ $result
+ );
+ }
+
+ public function testFormatPropertyItemOnPredefinedProperty() {
+
+ $property = $this->dataItemFactory->newDIProperty( '_MDAT' );
+
+ $instance = new WantedPropertiesQueryPage(
+ $this->store,
+ $this->settings
+ );
+
+ $result = $instance->formatResult(
+ $this->skin,
+ [ $property, 42 ]
+ );
+
+ $this->assertEmpty(
+ $result
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/AggregatablePrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/AggregatablePrinterTest.php
new file mode 100644
index 00000000..8bafa626
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/AggregatablePrinterTest.php
@@ -0,0 +1,335 @@
+<?php
+
+namespace SMW\Test;
+
+use ReflectionClass;
+use SMW\AggregatablePrinter;
+use SMWDataItem;
+use SMWDINumber;
+use SMWQueryResult;
+
+/**
+ * Tests for the AggregatablePrinter class
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * @covers \SMW\AggregatablePrinter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class AggregatablePrinterTest extends QueryPrinterTestCase {
+
+ /**
+ * Returns the name of the class to be tested
+ *
+ * @return string|false
+ */
+ public function getClass() {
+ return '\SMW\AggregatablePrinter';
+ }
+
+ /**
+ * Helper method that returns a AggregatablePrinter object
+ *
+ * @return AggregatablePrinter
+ */
+ private function newInstance( $parameters = [] ) {
+ return $this->setParameters( $this->getMockForAbstractClass( $this->getClass(), [ 'table' ] ), $parameters );
+ }
+
+ /**
+ * @dataProvider errorMessageProvider
+ *
+ * @since 1.9
+ */
+ public function testGetResultTextErrorMessage( $setup, $expected ) {
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getErrors', 'getNext', 'addErrors' ] )
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getNext' )
+ ->will( $this->returnValue( [] ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getErrors' )
+ ->will( $this->returnValue( [ $expected['message'] ] ) );
+
+ $instance = $this->newInstance( $setup['parameters'] );
+ // $queryResult = $setup['queryResult'];
+
+ $reflection = new ReflectionClass( '\SMW\AggregatablePrinter' );
+ $method = $reflection->getMethod( 'getResultText' );
+ $method->setAccessible( true );
+
+ $result = $method->invoke( $instance, $queryResult, SMW_OUTPUT_HTML );
+
+ $this->assertEmpty( $result );
+
+ foreach( $queryResult->getErrors() as $error ) {
+ $this->assertEquals( $expected['message'], $error );
+ }
+ }
+
+ /**
+ * @test AggregatablePrinter::addNumbersForDataItem
+ *
+ * @since 1.9
+ */
+ public function testAddNumbersForDataItem() {
+
+ $values = [];
+ $expected = [];
+ $keys = [ 'test', 'foo', 'bar' ];
+
+ $reflector = new ReflectionClass( '\SMW\AggregatablePrinter' );
+ $method = $reflector->getMethod( 'addNumbersForDataItem' );
+ $method->setAccessible( true );
+
+ for ( $i = 1; $i <= 10; $i++ ) {
+
+ // Select random array key
+ $name = $keys[rand(0, 2)];
+
+ // Get a random number
+ $random = rand( 10, 500 );
+
+ // Set expected result and create dataItem
+ $expected[$name] = isset( $expected[$name] ) ? $expected[$name] + $random : $random;
+ $dataItem = new SMWDINumber( $random );
+
+ $this->assertEquals( $random, $dataItem->getNumber() );
+ $this->assertEquals( SMWDataItem::TYPE_NUMBER, $dataItem->getDIType() );
+
+ // Invoke the instance
+ $result = $method->invokeArgs( $this->newInstance(), [ $dataItem, &$values, $name ] );
+
+ $this->assertInternalType( 'integer', $values[$name] );
+ $this->assertEquals( $expected[$name], $values[$name] );
+ }
+ }
+
+ /**
+ * @dataProvider numberDataProvider
+ *
+ * @since 1.9
+ */
+ public function testGetNumericResults( $setup, $expected ) {
+
+ $instance = $this->newInstance( $setup['parameters'] );
+
+ $reflector = new ReflectionClass( '\SMW\AggregatablePrinter' );
+ $method = $reflector->getMethod( 'getNumericResults' );
+ $method->setAccessible( true );
+
+ $result = $method->invoke( $instance, $setup['queryResult'], SMW_OUTPUT_HTML );
+
+ $this->assertInternalType(
+ 'array',
+ $result,
+ 'Asserts that getNumericResults() returns an array'
+ );
+
+ $this->assertEquals(
+ $expected['result'],
+ $result,
+ 'Asserts that the getNumericResults() output matches the expected result'
+ );
+
+ }
+
+ /**
+ * @return array
+ */
+ public function errorMessageProvider() {
+
+ $message = wfMessage( 'smw-qp-aggregatable-empty-data' )->inContentLanguage()->text();
+
+ $provider = [];
+
+ $provider[] = [
+ [
+ 'parameters' => [ 'distribution' => true ],
+ // 'queryResult' => $queryResult
+ ],
+ [
+ 'message' => $message
+ ]
+ ];
+
+ // #1
+ $provider[] = [
+ [
+ 'parameters' => [ 'distribution' => false ],
+ // 'queryResult' => $queryResult
+ ],
+ [
+ 'message' => $message
+ ]
+ ];
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function numberDataProvider() {
+
+ $provider = [];
+
+ $setup = [
+ [ 'printRequest' => 'Foo', 'number' => 10, 'dataValue' => 'Quuey' ],
+ [ 'printRequest' => 'Bar', 'number' => 20, 'dataValue' => 'Quuey' ],
+ [ 'printRequest' => 'Bar', 'number' => 20, 'dataValue' => 'Xuuey' ]
+ ];
+
+ // #0 aggregation = subject
+ $parameters = [
+ 'headers' => SMW_HEADERS_PLAIN,
+ 'offset' => 0,
+ 'aggregation' => 'subject',
+ 'mainlabel' => ''
+ ];
+
+ $provider[] = [
+ [
+ 'parameters' => $parameters,
+ 'queryResult' => $this->buildMockQueryResult( $setup )
+ ],
+ [
+ 'result' => [ 'Quuey' => 50 ]
+ ]
+ ];
+
+ // #1 aggregation = property
+ $parameters = [
+ 'headers' => SMW_HEADERS_PLAIN,
+ 'offset' => 0,
+ 'aggregation' => 'property',
+ 'mainlabel' => ''
+ ];
+
+ $provider[] = [
+ [
+ 'parameters' => $parameters,
+ 'queryResult' => $this->buildMockQueryResult( $setup )
+ ],
+ [
+ 'result' => [ 'Foo' => 10, 'Bar' => 40 ]
+ ]
+ ];
+
+ return $provider;
+ }
+
+ /**
+ * @return SMWQueryResult
+ */
+ private function buildMockQueryResult( $setup ) {
+
+ $printRequests = [];
+ $resultArrays = [];
+
+ foreach ( $setup as $value ) {
+
+ $printRequest = $this->getMockBuilder( '\SMW\Query\PrintRequest' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( $value['printRequest'] ) );
+
+ $printRequest->expects( $this->any() )
+ ->method( 'getLabel' )
+ ->will( $this->returnValue( $value['printRequest'] ) );
+
+ $printRequests[] = $printRequest;
+
+ $dataItem = $this->getMockBuilder( '\SMWDINumber' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataItem->expects( $this->any() )
+ ->method( 'getDIType' )
+ ->will( $this->returnValue( SMWDataItem::TYPE_NUMBER ) );
+
+ $dataItem->expects( $this->any() )
+ ->method( 'getNumber' )
+ ->will( $this->returnValue( $value['number'] ) );
+
+ $dataValue = $this->getMockBuilder( '\SMWNumberValue' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getTypeID' )
+ ->will( $this->returnValue( '_num' ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getShortWikiText' )
+ ->will( $this->returnValue( $value['dataValue'] ) );
+
+ $dataValue->expects( $this->any() )
+ ->method( 'getDataItem' )
+ ->will( $this->returnValue( $dataItem ) );
+
+ $resultArray = $this->getMockBuilder( '\SMWResultArray' )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'getText', 'getPrintRequest', 'getNextDataValue', 'getNextDataItem' ] )
+ ->getMock();
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getText' )
+ ->will( $this->returnValue( $value['printRequest'] ) );
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getPrintRequest' )
+ ->will( $this->returnValue( $printRequest ) );
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getNextDataValue' )
+ ->will( $this->onConsecutiveCalls( $dataValue, false ) );
+
+ $resultArray->expects( $this->any() )
+ ->method( 'getNextDataItem' )
+ ->will( $this->onConsecutiveCalls( $dataItem, false ) );
+
+ $resultArrays[] = $resultArray;
+ }
+
+ $queryResult = $this->getMockBuilder( '\SMWQueryResult' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getPrintRequests' )
+ ->will( $this->returnValue( $printRequests ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getNext' )
+ ->will( $this->onConsecutiveCalls( $resultArrays, false ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'getLink' )
+ ->will( $this->returnValue( new \SMWInfolink( true, 'Lala', 'Lula' ) ) );
+
+ $queryResult->expects( $this->any() )
+ ->method( 'hasFurtherResults' )
+ ->will( $this->returnValue( true ) );
+
+ return $queryResult;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/DsvResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/DsvResultPrinterTest.php
new file mode 100644
index 00000000..a9e631d3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/DsvResultPrinterTest.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\DsvResultPrinter;
+
+/**
+ * @covers \SMW\DsvResultPrinter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class DsvResultPrinterTest extends QueryPrinterTestCase {
+
+ /**
+ * @return string|false
+ */
+ public function getClass() {
+ return '\SMW\DsvResultPrinter';
+ }
+
+ /**
+ * @return DsvResultPrinter
+ */
+ private function getInstance( $parameters = [] ) {
+ return $this->setParameters( new DsvResultPrinter( 'dsv' ), $parameters );
+ }
+
+ public function testCanConstruc() {
+
+ $this->assertInstanceOf(
+ '\SMW\DsvResultPrinter',
+ $this->getInstance()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/EmbeddedResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/EmbeddedResultPrinterTest.php
new file mode 100644
index 00000000..9aa8a9fc
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/EmbeddedResultPrinterTest.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\EmbeddedResultPrinter;
+
+/**
+ * @covers \SMW\EmbeddedResultPrinter
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class EmbeddedResultPrinterTest extends QueryPrinterTestCase {
+
+ /**
+ * @return string|false
+ */
+ public function getClass() {
+ return '\SMW\EmbeddedResultPrinter';
+ }
+
+ /**
+ * @return SMWEmbeddedResultPrinter
+ */
+ private function getInstance( $parameters = [] ) {
+ return $this->setParameters( new EmbeddedResultPrinter( 'embedded' ), $parameters );
+ }
+
+ public function testcanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\EmbeddedResultPrinter',
+ $this->getInstance()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/JsonResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/JsonResultPrinterTest.php
new file mode 100644
index 00000000..8437760f
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/JsonResultPrinterTest.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace SMW\Test;
+
+use ReflectionClass;
+use SMW\JsonResultPrinter;
+use SMW\Tests\Utils\Mock\CoreMockObjectRepository;
+use SMW\Tests\Utils\Mock\MockObjectBuilder;
+
+/**
+ * @covers \SMW\JsonResultPrinter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @licence GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class JsonResultPrinterTest extends QueryPrinterTestCase {
+
+ protected $mockBuilder;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->mockBuilder = new MockObjectBuilder();
+ $this->mockBuilder->registerRepository( new CoreMockObjectRepository() );
+ }
+
+ /**
+ * @return string|false
+ */
+ public function getClass() {
+ return '\SMW\JsonResultPrinter';
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @return JsonResultPrinter
+ */
+ private function newInstance( $parameters = [] ) {
+ return $this->setParameters( new JsonResultPrinter( 'json' ), $parameters );
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testConstructor() {
+ $this->assertInstanceOf( $this->getClass(), $this->newInstance() );
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testGetMimeType() {
+
+ $this->assertEquals(
+ 'application/json',
+ $this->newInstance()->getMimeType( $this->mockBuilder->newObject( 'QueryResult' ) ),
+ 'Asserts that getMimeType() yields an expected result'
+ );
+
+ }
+
+ /**
+ * @dataProvider filenameDataProvider
+ *
+ * @since 1.9
+ */
+ public function testGetFileName( $filename, $expected ) {
+
+ $instance = $this->newInstance( [ 'searchlabel' => $filename ] );
+
+ $this->assertEquals(
+ $expected,
+ $instance->getFileName( $this->mockBuilder->newObject( 'QueryResult' ) ),
+ 'Asserts that getFileName() yields an expected result');
+ }
+
+ /**
+ * @return array
+ */
+ public function filenameDataProvider() {
+
+ $provider = [];
+
+ $provider[] = [ 'Lala', 'Lala.json' ];
+ $provider[] = [ 'Lala Lilu', 'Lala_Lilu.json' ];
+ $provider[] = [ '' , 'result.json'];
+
+ return $provider;
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testGetResultText() {
+
+ $result = [
+ 'lala' => __METHOD__,
+ 'lula' => 999388383838
+ ];
+
+ $expected = array_merge( $result, [ 'rows' => count( $result ) ] );
+
+ $instance = $this->newInstance( [ 'prettyprint' => false, 'unescape' => false ] );
+
+ $reflector = new ReflectionClass( '\SMW\JsonResultPrinter' );
+ $getResultText = $reflector->getMethod( 'getResultText' );
+ $getResultText->setAccessible( true );
+
+ $queryResult = $this->mockBuilder->newObject( 'QueryResult', [
+ 'serializeToArray' => $result,
+ 'getCount' => count( $result )
+ ] );
+
+ $results = $getResultText->invoke( $instance, $queryResult, SMW_OUTPUT_FILE );
+
+ $this->assertInternalType( 'string', $results );
+ $this->assertEquals( json_encode( $expected ), $results );
+
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RawResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RawResultPrinterTest.php
new file mode 100644
index 00000000..bfd759d8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RawResultPrinterTest.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\RawResultPrinter;
+
+/**
+ * @covers \SMW\RawResultPrinter
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class RawResultPrinterTest extends QueryPrinterTestCase {
+
+ /**
+ * @return string|false
+ */
+ public function getClass() {
+ return '\SMW\RawResultPrinter';
+ }
+
+ /**
+ * @return RawResultPrinter
+ */
+ private function getInstance( $parameters = [] ) {
+
+ $instance = $this->getMockBuilder( '\SMW\RawResultPrinter' )
+ ->disableOriginalConstructor()
+ ->setConstructorArgs( [ 'api' ] )
+ ->getMockForAbstractClass();
+
+ return $this->setParameters( $instance, $parameters );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMW\RawResultPrinter',
+ $this->getInstance()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RdfResultPrinterTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RdfResultPrinterTest.php
new file mode 100644
index 00000000..debdc0cb
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/RdfResultPrinterTest.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\RdfResultPrinter;
+
+/**
+ * @covers \SMW\RdfResultPrinter
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class RdfResultPrinterTest extends QueryPrinterTestCase {
+
+ /**
+ * @return string|false
+ */
+ public function getClass() {
+ return '\SMW\RdfResultPrinter';
+ }
+
+ /**
+ * @return RdfResultPrinter
+ */
+ private function getInstance( $parameters = [] ) {
+ return $this->setParameters( new RdfResultPrinter( 'rdf' ), $parameters );
+ }
+
+ public function testConstructor() {
+
+ $this->assertInstanceOf(
+ '\SMW\RdfResultPrinter',
+ $this->getInstance()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/ResultPrintersTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/ResultPrintersTest.php
new file mode 100644
index 00000000..04616ee3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/queryprinters/ResultPrintersTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace SMW\Test;
+
+use ParamProcessor\ParamDefinition;
+use SMW\ResultPrinter;
+use SMWQueryProcessor;
+
+/**
+ * Does some basic tests for the SMW\ResultPrinter deriving classes
+ *
+ * @since 1.9
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ */
+
+/**
+ * @covers \SMW\ResultPrinter
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class ResultPrintersTest extends QueryPrinterTestCase {
+
+ /**
+ * Returns the name of the class to be tested
+ *
+ * @return string|false
+ */
+ public function getClass() {
+ return false;
+ }
+
+ public function constructorProvider() {
+ global $smwgResultFormats;
+
+ $formats = [];
+
+ foreach ( $smwgResultFormats as $format => $class ) {
+ $formats[] = [ $format, $class, true ];
+ $formats[] = [ $format, $class, false ];
+ }
+
+ return $formats;
+ }
+
+ /**
+ * @dataProvider constructorProvider
+ *
+ * @param string $format
+ * @param string $class
+ * @param boolean $isInline
+ */
+ public function testConstructor( $format, $class, $isInline ) {
+ $instance = new $class( $format, $isInline );
+ $this->assertInstanceOf( '\SMWIResultPrinter', $instance );
+ }
+
+ public function instanceProvider() {
+ global $smwgResultFormats;
+
+ $instances = [];
+
+ foreach ( $smwgResultFormats as $format => $class ) {
+ $instances[] = new $class( $format, true );
+ }
+
+ return $this->arrayWrap( $instances );
+ }
+
+ /**
+ * @dataProvider instanceProvider
+ *
+ * @param \SMWResultPrinter $printer
+ */
+ public function testGetParamDefinitions( ResultPrinter $printer ) {
+ $params = $printer->getParamDefinitions( SMWQueryProcessor::getParameters( null, $printer ) );
+
+ $params = ParamDefinition::getCleanDefinitions( $params );
+
+ $this->assertInternalType( 'array', $params );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialConceptsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialConceptsTest.php
new file mode 100644
index 00000000..5835aefa
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialConceptsTest.php
@@ -0,0 +1,94 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\DIWikiPage;
+use SMW\SpecialConcepts;
+use SMW\Tests\Utils\UtilityFactory;
+use Title;
+use SMW\Tests\TestEnvironment;
+
+/**
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SpecialConceptsTest extends \PHPUnit_Framework_TestCase {
+
+ private $stringValidator;
+ private $testEnvironment;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->testEnvironment = new TestEnvironment();
+ $this->stringValidator = $this->testEnvironment->newValidatorFactory()->newStringValidator();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ SpecialConcepts::class,
+ new SpecialConcepts()
+ );
+ }
+
+ public function testExecute() {
+
+ $expected = 'p class="smw-special-concept-docu plainlinks"';
+
+ $outputPage = $this->getMockBuilder( '\OutputPage' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $outputPage->expects( $this->atLeastOnce() )
+ ->method( 'addHtml' )
+ ->with( $this->stringContains( $expected ) );
+
+ $query = '';
+ $instance = new SpecialConcepts();
+
+ $instance->getContext()->setTitle(
+ Title::newFromText( 'SemanticMadiaWiki' )
+ );
+
+ $oldOutput = $instance->getOutput();
+
+ $instance->getContext()->setOutput( $outputPage );
+ $instance->execute( $query );
+
+ // Context is static avoid any succeeding tests to fail
+ $instance->getContext()->setOutput( $oldOutput );
+ }
+
+ /**
+ * @depends testExecute
+ */
+ public function testGetHtmlForAnEmptySubject() {
+
+ $instance = new SpecialConcepts();
+
+ $this->stringValidator->assertThatStringContains(
+ 'div class="smw-special-concept-empty"',
+ $instance->getHtml( [], 0, 0 )
+ );
+ }
+
+ /**
+ * @depends testGetHtmlForAnEmptySubject
+ */
+ public function testGetHtmlForSingleSubject() {
+
+ $subject = DIWikiPage::newFromText( __METHOD__ );
+ $instance = new SpecialConcepts();
+
+ $this->stringValidator->assertThatStringContains(
+ 'div class="smw-special-concept-count"',
+ $instance->getHtml( [ $subject ], 1, 0 )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialsTest.php
new file mode 100644
index 00000000..4447ed28
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/specials/SpecialsTest.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace SMW\Test;
+
+use FauxRequest;
+use Language;
+use RequestContext;
+use SpecialPage;
+use SpecialPageFactory;
+
+/**
+ * Tests for registered special pages
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
+ * @author mwjames
+ */
+
+/**
+ * @covers \SMW\SpecialWantedProperties
+ * @covers \SMW\SpecialUnusedProperties
+ * @covers \SMW\SpecialProperties
+ * @covers \SMW\SpecialConcepts
+ * @covers \SMW\SpecialPage
+ * @covers \SMW\MediaWiki\Specials\SpecialAsk
+ * @covers \SMW\MediaWiki\Specials\SpecialAdmin
+ * @covers \SMW\MediaWiki\Specials\SpecialBrowse
+ * @covers \SMW\MediaWiki\Specials\SpecialSearchByProperty
+ *
+ * @note Test base was borrowed from the EducationProgram extension
+ *
+ * @group SMW
+ * @group SMWExtension
+ * @group medium
+ */
+class SpecialsTest extends SemanticMediaWikiTestCase {
+
+ /**
+ * Returns the name of the class to be tested
+ *
+ * @return string|false
+ */
+ public function getClass() {
+ return false;
+ }
+
+ /**
+ * @dataProvider specialPageProvider
+ *
+ * @param $specialPage
+ */
+ public function testSpecial( SpecialPage $specialPage ) {
+
+ try {
+ $specialPage->execute( '' );
+ }
+ catch ( \Exception $exception ) {
+ if ( !( $exception instanceof \PermissionsError ) && !( $exception instanceof \ErrorPageError ) ) {
+ throw $exception;
+ }
+ }
+
+ $this->assertTrue( true, 'SpecialPage test did run without errors' );
+ }
+
+ /**
+ * @test SpecialPageFactory::getLocalNameFor
+ * @dataProvider specialPageProvider
+ *
+ * Test created in response to bug 44191
+ *
+ * @param $specialPage
+ */
+ public function testSpecialAliasesContLang( SpecialPage $specialPage ) {
+
+ // Test for languages
+ $langCodes = [ 'en', 'fr', 'de', 'es', 'zh', 'ja' ];
+
+ // Test aliases for a specific language
+ foreach ( $langCodes as $langCode ) {
+ $langObj = Language::factory( $langCode );
+ $aliases = $langObj->getSpecialPageAliases();
+ $found = false;
+ $name = $specialPage->getName();
+
+ // Check against available aliases
+ foreach ( $aliases as $n => $values ) {
+ foreach ( $values as $value ) {
+ if( $name === $value ) {
+ $found = true;
+ break;
+ }
+ }
+ }
+
+ $this->assertTrue(
+ $found,
+ "{$name} alias not found in language {$langCode}"
+ );
+ }
+ }
+
+ /**
+ * Provides special pages
+ *
+ * @return array
+ */
+ public function specialPageProvider() {
+ $request = new FauxRequest( [], true );
+ $argLists = [];
+
+ $specialPages = [
+ 'Ask',
+ 'Browse',
+ 'PageProperty',
+ 'SearchByProperty',
+ 'SMWAdmin',
+ 'ExportRDF',
+ 'Types',
+ 'Properties',
+ 'UnusedProperties',
+ 'WantedProperties',
+ 'Concepts',
+ 'ProcessingErrorList',
+ 'PropertyLabelSimilarity',
+ 'URIResolver'
+ ];
+
+ foreach ( $specialPages as $special ) {
+
+ $specialPage = SpecialPageFactory::getPage(
+ $special
+ );
+
+ // Deprecated: Use of SpecialPage::getTitle was deprecated in MediaWiki 1.23
+ $title = method_exists( $specialPage, 'getPageTitle') ? $specialPage->getPageTitle() : $specialPage->getTitle();
+
+ $context = RequestContext::newExtraneousContext( $title );
+ $context->setRequest( $request );
+
+ $specialPage->setContext( clone $context );
+ $argLists[] = [ clone $specialPage ];
+
+ $context->setUser( $this->getUser() );
+ $specialPage->setContext( $context );
+ $argLists[] = [ $specialPage ];
+ }
+
+ return $argLists;
+ }
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/QueryResultTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/QueryResultTest.php
new file mode 100644
index 00000000..61e74563
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/QueryResultTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\DIWikiPage;
+use SMWQueryResult as QueryResult;
+
+/**
+ * @covers \SMWQueryResult
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class QueryResultTest extends \PHPUnit_Framework_TestCase {
+
+ public function testCanConstruct() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $printRequests = [];
+ $results = [];
+
+ $this->assertInstanceOf(
+ '\SMWQueryResult',
+ new QueryResult( $printRequests, $query, $results, $store )
+ );
+ }
+
+ public function testVerifyThatAfterSerializeToArrayResultNextCanBeUsed() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $printRequests = [];
+
+ $results = [
+ new DIWikiPage( 'Foo', 0 ),
+ new DIWikiPage( 'Bar', 0 )
+ ];
+
+ $instance = new QueryResult( $printRequests, $query, $results, $store );
+
+ $instance->serializeToArray();
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getNext()
+ );
+
+ $instance->getHash();
+
+ $this->assertInternalType(
+ 'array',
+ $instance->getNext()
+ );
+ }
+
+ public function testIsFromCache() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $printRequests = [];
+ $results = [];
+
+ $instance = new QueryResult(
+ $printRequests,
+ $query,
+ $results,
+ $store
+ );
+
+ $this->assertFalse(
+ $instance->isFromCache()
+ );
+
+ $instance->setFromCache( true );
+
+ $this->assertTrue(
+ $instance->isFromCache()
+ );
+ }
+
+ public function testGetHash() {
+
+ $query = $this->getMockBuilder( '\SMWQuery' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( '\SMW\Store' )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $printRequests = [];
+ $results = [];
+
+ $instance = new QueryResult(
+ $printRequests,
+ $query,
+ $results,
+ $store
+ );
+
+ $this->assertNotSame(
+ $instance->getHash( 'quick' ),
+ $instance->getHash()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreFactoryTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreFactoryTest.php
new file mode 100644
index 00000000..90415200
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreFactoryTest.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace SMW\Tests;
+
+use SMW\Settings;
+use SMW\StoreFactory;
+
+/**
+ * @covers \SMW\StoreFactory
+ *
+ *
+ * @group SMW
+ * @group SMWExtension
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class StoreFactoryTest extends \PHPUnit_Framework_TestCase {
+
+ use PHPUnitCompat;
+
+ protected function tearDown() {
+ StoreFactory::clear();
+
+ parent::tearDown();
+ }
+
+ public function testGetDefaultStore() {
+
+ $instance = StoreFactory::getStore();
+
+ $this->assertInstanceOf(
+ Settings::newFromGlobals()->get( 'smwgDefaultStore' ),
+ $instance
+ );
+
+ $this->assertSame(
+ StoreFactory::getStore(),
+ $instance
+ );
+
+ StoreFactory::clear();
+
+ $this->assertNotSame(
+ StoreFactory::getStore(),
+ $instance
+ );
+ }
+
+ public function testDifferentStoreIdInstanceInvocation() {
+
+ $this->assertInstanceOf( 'SMW\Store', StoreFactory::getStore( '\SMWSQLStore3' ) );
+ $this->assertInstanceOf( 'SMW\Store', StoreFactory::getStore( '\SMWSparqlStore' ) );
+
+ $this->assertNotSame(
+ StoreFactory::getStore( '\SMWSQLStore3' ),
+ StoreFactory::getStore( '\SMWSparqlStore' )
+ );
+ }
+
+ public function testStoreInstanceException() {
+ $this->setExpectedException( '\SMW\Exception\StoreNotFoundException' );
+ StoreFactory::getStore( '\SMW\StoreFactory' );
+ }
+
+ public function testStoreWithInvalidClassThrowsException() {
+ $this->setExpectedException( 'RuntimeException' );
+ StoreFactory::getStore( 'foo' );
+ }
+
+ /**
+ * smwfGetStore is deprecated but due to its dependency do a quick check here
+ *
+ * FIXME Delete this test in 1.11
+ */
+ public function testSmwfGetStore() {
+ $store = smwfGetStore();
+
+ $this->assertInstanceOf( 'SMWStore', $store );
+ $this->assertInstanceOf( 'SMW\Store', $store );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreTest.php
new file mode 100644
index 00000000..2b60cf46
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/StoreTest.php
@@ -0,0 +1,198 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\Connection\ConnectionManager;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\StoreFactory;
+use SMW\Tests\MwDBaseUnitTestCase;
+use SMWRequestOptions;
+use Title;
+
+/**
+ * Tests for the SMWStore class.
+ *
+ * @since 1.8
+ *
+ * @group SMW
+ * @group SMWStore
+ * @group SMWExtension
+ * @group Database
+ *
+ * @author Nischay Nahata
+ */
+class StoreTest extends MwDBaseUnitTestCase {
+
+///// Reading methods /////
+
+ public function getSemanticDataProvider() {
+ return [
+ [ Title::newMainPage()->getFullText() ],
+ ];
+ }
+
+ /**
+ * @dataProvider getSemanticDataProvider
+ */
+ public function testGetSemanticData( $titleText ,$filter = false) {
+ $title = Title::newFromText( $titleText );
+ $subject = DIWikiPage::newFromTitle( $title );
+ $store = StoreFactory::getStore();
+
+ $this->assertInstanceOf(
+ '\SMW\SemanticData',
+ $store->getSemanticData( $subject, $filter ),
+ "Result should be instance of SMWSemanticData."
+ );
+ }
+
+ public function getPropertyValuesDataProvider() {
+ return [
+ [ Title::newMainPage()->getFullText(), new DIProperty('_MDAT') ],
+ [ Title::newMainPage()->getFullText(), DIProperty::newFromUserLabel('Age') ],
+ ];
+ }
+
+ /**
+ * @dataProvider getPropertyValuesDataProvider
+ */
+ public function testGetPropertyValues( $titleText, DIProperty $property, $requestOptions = null ) {
+ $title = Title::newFromText( $titleText );
+ $subject = DIWikiPage::newFromTitle( $title );
+ $store = StoreFactory::getStore();
+ $result = $store->getPropertyValues( $subject, $property, $requestOptions );
+
+ $this->assertInternalType( 'array', $result );
+ $this->assertContainsOnlyInstancesOf( '\SMWDataItem', $result );
+ }
+
+ public function getPropertySubjectsDataProvider() {
+ return [
+ [ new DIProperty('_MDAT'), null ],
+ ];
+ }
+
+ /**
+ * @dataProvider getPropertySubjectsDataProvider
+ */
+ public function testGetPropertySubjects( DIProperty $property, $value, $requestOptions = null ) {
+ $store = StoreFactory::getStore();
+ $result = $store->getPropertySubjects( $property, $value, $requestOptions );
+
+ $this->assertInstanceOf(
+ '\Iterator',
+ $result
+ );
+
+ foreach( $result as $page ) {
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $page,
+ "Result should be instance of DIWikiPage."
+ );
+ }
+ }
+
+ public function getPropertiesDataProvider() {
+ return [
+ [ Title::newMainPage()->getFullText() ],
+ ];
+ }
+
+ /**
+ * @dataProvider getPropertiesDataProvider
+ */
+ public function testGetProperties( $titleText, $requestOptions = null ) {
+ $title = Title::newFromText( $titleText );
+ $subject = DIWikiPage::newFromTitle( $title );
+ $store = StoreFactory::getStore();
+ $result = $store->getProperties( $subject, $requestOptions );
+
+ $this->assertTrue( is_array( $result ) );
+
+ foreach( $result as $property ) {
+ $this->assertInstanceOf(
+ '\SMWDataItem',
+ $property,
+ "Result should be instance of DIProperty."
+ );
+ }
+ }
+
+///// Special page functions /////
+
+ public function testGetPropertiesSpecial() {
+ // Really bailing out here and making the test database dependent!!
+
+ // This test fails on mysql http://bugs.mysql.com/bug.php?id=10327
+ if( $GLOBALS['wgDBtype'] == 'mysql' ) {
+ $this->assertTrue( true );
+ return;
+ }
+
+ $store = StoreFactory::getStore();
+ $result = $store->getPropertiesSpecial( new SMWRequestOptions() );
+
+ $this->assertInstanceOf( '\SMW\SQLStore\Lookup\ListLookup', $result );
+ foreach( $result->fetchList() as $row ) {
+ $this->assertCount( 2, $row );
+
+ $this->assertInstanceOf(
+ '\SMWDataItem',
+ $row[0],
+ "Result should be DataItem instance."
+ );
+ }
+ }
+
+ public function testGetUnusedPropertiesSpecial() {
+ $store = StoreFactory::getStore();
+ $result = $store->getUnusedPropertiesSpecial( new SMWRequestOptions() );
+
+ $this->assertInstanceOf( '\SMW\SQLStore\Lookup\ListLookup', $result );
+ foreach( $result->fetchList() as $row ) {
+ $this->assertInstanceOf(
+ '\SMWDataItem',
+ $row,
+ "Result should be instance of DIProperty."
+ );
+ }
+ }
+
+ public function testGetWantedPropertiesSpecial() {
+ $store = StoreFactory::getStore();
+ $result = $store->getWantedPropertiesSpecial( new SMWRequestOptions() );
+
+ $this->assertInstanceOf( '\SMW\SQLStore\Lookup\ListLookup', $result );
+ foreach( $result->fetchList() as $row ) {
+ $this->assertInstanceOf(
+ '\SMW\DIProperty',
+ $row[0],
+ "Result should be instance of DIProperty."
+ );
+ }
+ }
+
+ public function testGetStatistics() {
+ $store = StoreFactory::getStore();
+ $result = $store->getStatistics();
+
+ $this->assertTrue( is_array( $result ) );
+ $this->assertArrayHasKey( 'PROPUSES', $result );
+ $this->assertArrayHasKey( 'USEDPROPS', $result );
+ $this->assertArrayHasKey( 'DECLPROPS', $result );
+ }
+
+ public function testConnection() {
+
+ $store = StoreFactory::getStore();
+ $store->setConnectionManager( new ConnectionManager() );
+
+ $this->assertInstanceOf(
+ '\SMW\MediaWiki\Database',
+ $store->getConnection( 'mw.db' )
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreSmwIdsTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreSmwIdsTest.php
new file mode 100644
index 00000000..54b913f1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreSmwIdsTest.php
@@ -0,0 +1,546 @@
+<?php
+
+namespace SMW\Tests\SQLStore;
+
+use Onoi\Cache\FixedInMemoryLruCache;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\SQLStore\EntityStore\IdCacheManager;
+use SMW\SQLStore\RedirectStore;
+use SMWSql3SmwIds;
+
+/**
+ * @covers \SMWSql3SmwIds
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.1
+ *
+ * @author mwjames
+ */
+class SQLStoreSmwIdsTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+ private $cache;
+ private $idMatchFinder;
+ private $uniquenessLookup;
+ private $factory;
+
+ protected function setUp() {
+
+ $idCacheManager = new IdCacheManager(
+ [
+ 'entity.id' => new FixedInMemoryLruCache(),
+ 'entity.sort' => new FixedInMemoryLruCache(),
+ 'entity.lookup' => new FixedInMemoryLruCache(),
+ 'table.hash' => new FixedInMemoryLruCache()
+ ]
+ );
+
+ $this->cache = $this->getMockBuilder( '\Onoi\Cache\Cache' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $propertyStatisticsStore = $this->getMockBuilder( '\SMW\SQLStore\PropertyStatisticsStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->idEntityFinder = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\IdEntityFinder' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->uniquenessLookup = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\UniquenessLookup' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $redirectStore = new RedirectStore( $this->store );
+
+ $this->factory = $this->getMockBuilder( '\SMW\SQLStore\SQLStoreFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newUniquenessLookup' )
+ ->will( $this->returnValue( $this->uniquenessLookup ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newIdCacheManager' )
+ ->will( $this->returnValue( $idCacheManager ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newRedirectStore' )
+ ->will( $this->returnValue( $redirectStore ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newPropertyStatisticsStore' )
+ ->will( $this->returnValue( $propertyStatisticsStore ) );
+
+ $this->factory->expects( $this->any() )
+ ->method( 'newidEntityFinder' )
+ ->will( $this->returnValue( $this->idEntityFinder ) );
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWSql3SmwIds',
+ new SMWSql3SmwIds( $this->store, $this->factory )
+ );
+ }
+
+ public function testRedirectInfoRoundtrip() {
+
+ $subject = new DIWikiPage( 'Foo', 9001 );
+
+ $instance = new SMWSql3SmwIds(
+ $this->store,
+ $this->factory
+ );
+
+ $this->assertFalse(
+ $instance->isRedirect( $subject )
+ );
+
+ $instance->addRedirect( 42, 'Foo', 9001 );
+
+ $this->assertEquals(
+ 42,
+ $instance->findRedirect( 'Foo', 9001 )
+ );
+
+ $this->assertTrue(
+ $instance->isRedirect( $subject )
+ );
+
+ $instance->deleteRedirect( 'Foo', 9001 );
+
+ $this->assertEquals(
+ 0,
+ $instance->findRedirect( 'Foo', 9001 )
+ );
+
+ $this->assertFalse(
+ $instance->isRedirect( $subject )
+ );
+ }
+
+ public function testGetPropertyId() {
+
+ $selectRow = new \stdClass;
+ $selectRow->smw_id = 9999;
+ $selectRow->smw_sort = '';
+ $selectRow->smw_sortkey = 'Foo';
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( $selectRow ) );
+
+ $store = $this->getMockBuilder( 'SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SMWSql3SmwIds(
+ $store,
+ $this->factory
+ );
+
+ $result = $instance->getSMWPropertyID( new DIProperty( 'Foo' ) );
+
+ $this->assertEquals( 9999, $result );
+ }
+
+ /**
+ * @dataProvider pageIdandSortProvider
+ */
+ public function testGetSMWPageIDandSort( $parameters ) {
+
+ $selectRow = new \stdClass;
+ $selectRow->smw_id = 9999;
+ $selectRow->smw_sort = '';
+ $selectRow->smw_sortkey = 'Foo';
+ $selectRow->smw_proptable_hash = serialize( 'Foo' );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( $selectRow ) );
+
+ $store = $this->getMockBuilder( 'SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SMWSql3SmwIds(
+ $store,
+ $this->factory
+ );
+
+ $sortkey = $parameters['sortkey'];
+
+ $result = $instance->getSMWPageIDandSort(
+ $parameters['title'],
+ $parameters['namespace'],
+ $parameters['iw'],
+ $parameters['subobjectName'],
+ $sortkey, // pass-by-reference
+ $parameters['canonical'],
+ $parameters['fetchHashes']
+ );
+
+ $this->assertEquals( 9999, $result );
+ }
+
+ /**
+ * @dataProvider pageIdandSortProvider
+ */
+ public function testMakeSMWPageID( $parameters ) {
+
+ $selectRow = new \stdClass;
+ $selectRow->smw_id = 0;
+ $selectRow->o_id = 0;
+ $selectRow->smw_sort = '';
+ $selectRow->smw_sortkey = 'Foo';
+ $selectRow->smw_proptable_hash = serialize( 'Foo' );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->any() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( $selectRow ) );
+
+ $connection->expects( $this->once() )
+ ->method( 'insertId' )
+ ->will( $this->returnValue( 9999 ) );
+
+ $store = $this->getMockBuilder( 'SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SMWSql3SmwIds(
+ $store,
+ $this->factory
+ );
+
+ $sortkey = $parameters['sortkey'];
+
+ $result = $instance->makeSMWPageID(
+ $parameters['title'],
+ $parameters['namespace'],
+ $parameters['iw'],
+ $parameters['subobjectName'],
+ $sortkey,
+ $parameters['canonical'],
+ $parameters['fetchHashes']
+ );
+
+ $this->assertEquals( 9999, $result );
+ }
+
+ public function testGetDataItemById() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $this->idEntityFinder->expects( $this->once() )
+ ->method( 'getDataItemById' )
+ ->with( $this->equalTo( 42 ) )
+ ->will( $this->returnValue( new DIWikiPage( 'Foo', NS_MAIN ) ) );
+
+ $instance = new SMWSql3SmwIds(
+ $this->store,
+ $this->factory
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\DIWikiPage',
+ $instance->getDataItemById( 42 )
+ );
+ }
+
+ public function testUpdateInterwikiField() {
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'update' )
+ ->with(
+ $this->anything(),
+ $this->equalTo( [
+ 'smw_iw' => 'Bar',
+ 'smw_hash' => '8ba1886210e332a1fbaf28c38e43d1e89dc761db' ] ),
+ $this->equalTo( [ 'smw_id' => 42 ] ) );
+
+ $store = $this->getMockBuilder( 'SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SMWSql3SmwIds(
+ $store,
+ $this->factory
+ );
+
+ $instance->updateInterwikiField(
+ 42,
+ new DIWikiPage( 'Foo', NS_MAIN, 'Bar' )
+ );
+ }
+
+ public function testFindDuplicateEntries() {
+
+ $expected = [
+ 'count' => 2,
+ 'smw_title' => 'Foo',
+ 'smw_namespace' => 0,
+ 'smw_iw' => '',
+ 'smw_subobject' => ''
+ ];
+
+ $row = $expected;
+
+ $this->uniquenessLookup->expects( $this->once() )
+ ->method( 'findDuplicates' )
+ ->will( $this->returnValue( [ $row ] ) );
+
+ $instance = new SMWSql3SmwIds(
+ $this->store,
+ $this->factory
+ );
+
+ $this->assertEquals(
+ [ $expected ],
+ $instance->findDuplicates()
+ );
+ }
+
+ public function testGetIDOnPredefinedProperty() {
+
+ $row = new \stdClass;
+ $row->smw_id = 42;
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store = $this->getMockBuilder( 'SMWSQLStore3' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( $row ) );
+
+ $store->expects( $this->atLeastOnce() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SMWSql3SmwIds(
+ $store,
+ $this->factory
+ );
+
+ $this->assertEquals(
+ 29,
+ $instance->getId( new DIWikiPage( '_MDAT', SMW_NS_PROPERTY ) )
+ );
+
+ $this->assertEquals(
+ 42,
+ $instance->getId( new DIWikiPage( '_MDAT', SMW_NS_PROPERTY, '', 'Foo' ) )
+ );
+ }
+
+ public function testWarmUpCache() {
+
+ $row = [
+ 'smw_id' => 42,
+ 'smw_title' => 'Foo',
+ 'smw_namespace' => 0,
+ 'smw_iw' => '',
+ 'smw_subobject' => '',
+ 'smw_sortkey' => 'Foo',
+ 'smw_sort' => '',
+ ];
+
+ $idCacheManager = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\IdCacheManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $idCacheManager->expects( $this->once() )
+ ->method( 'setCache' );
+
+ $idCacheManager->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnValue( $this->cache ) );
+
+ $factory = $this->getMockBuilder( '\SMW\SQLStore\SQLStoreFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $factory->expects( $this->any() )
+ ->method( 'newIdCacheManager' )
+ ->will( $this->returnValue( $idCacheManager ) );
+
+ $factory->expects( $this->any() )
+ ->method( 'newIdEntityFinder' )
+ ->will( $this->returnValue( $this->idEntityFinder ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'select' )
+ ->will( $this->returnValue( [ (object)$row ] ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SMWSql3SmwIds(
+ $store,
+ $factory
+ );
+
+ $instance->warmUpCache( [ new DIWikiPage( 'Bar', NS_MAIN ) ] );
+ }
+
+ public function testFindAssociatedRev() {
+
+ $row = [
+ 'smw_id' => 42,
+ 'smw_title' => 'Foo',
+ 'smw_namespace' => 0,
+ 'smw_iw' => '',
+ 'smw_subobject' => '',
+ 'smw_sortkey' => 'Foo',
+ 'smw_sort' => '',
+ 'smw_rev' => 1001,
+ ];
+
+ $idCacheManager = $this->getMockBuilder( '\SMW\SQLStore\EntityStore\IdCacheManager' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $idCacheManager->expects( $this->any() )
+ ->method( 'get' )
+ ->will( $this->returnValue( $this->cache ) );
+
+ $factory = $this->getMockBuilder( '\SMW\SQLStore\SQLStoreFactory' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $factory->expects( $this->any() )
+ ->method( 'newIdCacheManager' )
+ ->will( $this->returnValue( $idCacheManager ) );
+
+ $factory->expects( $this->any() )
+ ->method( 'newIdEntityFinder' )
+ ->will( $this->returnValue( $this->idEntityFinder ) );
+
+ $connection = $this->getMockBuilder( '\SMW\MediaWiki\Database' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $connection->expects( $this->once() )
+ ->method( 'selectRow' )
+ ->will( $this->returnValue( (object)$row ) );
+
+ $store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $store->expects( $this->any() )
+ ->method( 'getConnection' )
+ ->will( $this->returnValue( $connection ) );
+
+ $instance = new SMWSql3SmwIds(
+ $store,
+ $factory
+ );
+
+ $this->assertEquals(
+ 1001,
+ $instance->findAssociatedRev( 'Foo', NS_MAIN, '', '' )
+ );
+ }
+
+ public function pageIdandSortProvider() {
+
+ $provider[] = [ 'Foo', NS_MAIN, '' , '', 'FOO', false, false ];
+ $provider[] = [ 'Foo', NS_MAIN, '' , '', 'FOO', true, false ];
+ $provider[] = [ 'Foo', NS_MAIN, '' , '', 'FOO', true, true ];
+ $provider[] = [ 'Foo', NS_MAIN, 'quy' , '', 'FOO', false, false ];
+ $provider[] = [ 'Foo', NS_MAIN, 'quy' , 'xwoo', 'FOO', false, false ];
+
+ $provider[] = [ 'pro', SMW_NS_PROPERTY, '' , '', 'PRO', false, false ];
+ $provider[] = [ 'pro', SMW_NS_PROPERTY, '' , '', 'PRO', true, false ];
+ $provider[] = [ 'pro', SMW_NS_PROPERTY, '' , '', 'PRO', true, true ];
+
+ return $this->createAssociativeArrayFromProviderDefinition( $provider );
+ }
+
+ private function createAssociativeArrayFromProviderDefinition( $definitions ) {
+
+ foreach ( $definitions as $map ) {
+ $provider[] = [ [
+ 'title' => $map[0],
+ 'namespace' => $map[1],
+ 'iw' => $map[2],
+ 'subobjectName' => $map[3],
+ 'sortkey' => $map[4],
+ 'canonical' => $map[5],
+ 'fetchHashes' => $map[6]
+ ] ];
+ }
+
+ return $provider;
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreTest.php b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreTest.php
new file mode 100644
index 00000000..d183273c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/phpunit/includes/storage/sqlstore/SQLStoreTest.php
@@ -0,0 +1,170 @@
+<?php
+
+namespace SMW\Test\SQLStore;
+
+use SMW\ApplicationFactory;
+use SMWSQLStore3;
+
+/**
+ * @covers \SMWSQLStore3
+ *
+ * @group semantic-mediawiki
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class SQLStoreTest extends \PHPUnit_Framework_TestCase {
+
+ private $store;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->store = new SMWSQLStore3();
+
+ $settings = [
+ 'smwgFixedProperties' => [],
+ 'smwgPageSpecialProperties' => []
+ ];
+
+ foreach ( $settings as $key => $value ) {
+ ApplicationFactory::getInstance()->getSettings()->set( $key, $value );
+ }
+ }
+
+ protected function tearDown() {
+ $this->store->clear();
+ ApplicationFactory::getInstance()->clear();
+
+ parent::tearDown();
+ }
+
+ public function testCanConstruct() {
+
+ $this->assertInstanceOf(
+ '\SMWSQLStore3',
+ $this->store
+ );
+
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\SQLStore',
+ $this->store
+ );
+ }
+
+ /**
+ * @depends testCanConstruct
+ */
+ public function testGetPropertyTables() {
+
+ $defaultPropertyTableCount = count( $this->store->getPropertyTables() );
+
+ $this->assertInternalType(
+ 'array',
+ $this->store->getPropertyTables()
+ );
+
+ foreach ( $this->store->getPropertyTables() as $tid => $propTable ) {
+ $this->assertInstanceOf(
+ '\SMW\SQLStore\TableDefinition',
+ $propTable
+ );
+ }
+ }
+
+ /**
+ * @depends testGetPropertyTables
+ */
+ public function testPropertyTablesValidCustomizableProperty() {
+
+ $defaultPropertyTableCount = count( $this->store->getPropertyTables() );
+
+ $settings = [
+ 'smwgFixedProperties' => [],
+ 'smwgPageSpecialProperties' => [ '_MDAT' ]
+ ];
+
+ foreach ( $settings as $key => $value ) {
+ ApplicationFactory::getInstance()->getSettings()->set( $key, $value );
+ }
+
+ $this->store->clear();
+
+ $this->assertCount(
+ $defaultPropertyTableCount + 1,
+ $this->store->getPropertyTables()
+ );
+ }
+
+ /**
+ * @depends testGetPropertyTables
+ */
+ public function testPropertyTablesWithInvalidCustomizableProperty() {
+
+ $defaultPropertyTableCount = count( $this->store->getPropertyTables() );
+
+ $settings = [
+ 'smwgFixedProperties' => [],
+ 'smwgPageSpecialProperties' => [ '_MDAT', 'Foo' ]
+ ];
+
+ foreach ( $settings as $key => $value ) {
+ ApplicationFactory::getInstance()->getSettings()->set( $key, $value );
+ }
+
+ $this->store->clear();
+
+ $this->assertCount(
+ $defaultPropertyTableCount + 1,
+ $this->store->getPropertyTables()
+ );
+ }
+
+ /**
+ * @depends testGetPropertyTables
+ */
+ public function testPropertyTablesWithValidCustomizableProperties() {
+
+ $defaultPropertyTableCount = count( $this->store->getPropertyTables() );
+
+ $settings = [
+ 'smwgFixedProperties' => [],
+ 'smwgPageSpecialProperties' => [ '_MDAT', '_MEDIA' ]
+ ];
+
+ foreach ( $settings as $key => $value ) {
+ ApplicationFactory::getInstance()->getSettings()->set( $key, $value );
+ }
+
+ $this->store->clear();
+
+ $this->assertCount(
+ $defaultPropertyTableCount + 2,
+ $this->store->getPropertyTables()
+ );
+ }
+
+ public function testGetStatisticsTable() {
+
+ $this->assertInternalType(
+ 'string',
+ $this->store->getStatisticsTable()
+ );
+ }
+
+ public function testGetObjectIds() {
+
+ $this->assertInternalType(
+ 'object',
+ $this->store->getObjectIds()
+ );
+
+ $this->assertInternalType(
+ 'string',
+ $this->store->getObjectIds()->getIdTable()
+ );
+ }
+
+}
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/api/ext.smw.api.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/api/ext.smw.api.test.js
new file mode 100644
index 00000000..8960e7d8
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/api/ext.smw.api.test.js
@@ -0,0 +1,190 @@
+/**
+ * This file is part of the Semantic MediaWiki QUnit test suite
+ * @see https://semantic-mediawiki.org/wiki/QUnit
+ *
+ * @section LICENSE
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ignore
+ *
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * Tests methods provided by ext.smw.api.js
+ * @ignore
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.Api', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.api();
+ assert.ok( result instanceof Object, pass + 'the api instance was accessible' );
+
+ } );
+
+ /**
+ * Test fetch
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'fetch()', function ( assert ) {
+ assert.expect( 4 );
+
+ var done = assert.async();
+
+ var smwApi = new smw.api();
+
+ assert.throws( function() { smwApi.fetch( '' , '' ); }, pass + 'an error was raised (query was empty)' );
+ assert.throws( function() { smwApi.fetch( {'foo': 'bar' } , '' ); }, pass + 'an error was raised (query was an object)' );
+
+ // Ajax
+ var query = '[[Modification date::+]]|?Modification date|limit=10|offset=0';
+
+ smwApi.fetch( query )
+ .done( function ( results ) {
+
+ assert.ok( true, pass + 'of an positive server response' );
+ assert.ok( results instanceof Object, pass + 'an object was returned' );
+
+ done();
+ } );
+
+ } );
+
+ /**
+ * Test caching
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'fetch() cache test', function ( assert ) {
+ assert.expect( 4 );
+
+ var smwApi = new smw.api();
+
+ // Ajax
+ var queryString = '[[Modification date::+]]|?Modification date|?Modification date|?Modification date|limit=100';
+ var undefCacheDone = assert.async();
+
+ smwApi.fetch( queryString )
+ .done( function ( results ) {
+ assert.equal( results.isCached, false , pass + ' caching is set "undefined" and results are not cached' );
+ undefCacheDone();
+ } );
+
+ var falseCacheDone = assert.async();
+ smwApi.fetch( queryString, false )
+ .done( function ( results ) {
+ assert.equal( results.isCached , false , pass + ' caching is set "false" and results are not cached' );
+ falseCacheDone();
+ } );
+
+ // Make sure the cache is initialized otherwise the asserts will fail
+ // for the first test run
+ var cacheDone = assert.async();
+ smwApi.fetch( queryString, true )
+ .done( function () {
+ var firstCacheDone = assert.async();
+
+ smwApi.fetch( queryString, 60 * 1000 )
+ .done( function ( results ) {
+ assert.equal( results.isCached , true , pass + ' caching is set to "60 * 1000" and results are cached' );
+ firstCacheDone();
+ } );
+
+ var otherCacheDone = assert.async();
+ smwApi.fetch( queryString, true )
+ .done( function ( results ) {
+ assert.equal( results.isCached , true , pass + ' caching is set "true" and results are cached' );
+ otherCacheDone();
+ } );
+
+ cacheDone();
+ } );
+
+ } );
+
+ /**
+ * Test fetch vs. a normal $.ajax call
+ *
+ * @since: 1.9
+ * @ignore since 2013 - should this test be removed?
+ */
+ QUnit.test( 'fetch() vs. $.ajax', function ( assert ) {
+ assert.expect( 3 );
+
+ var ajaxDone = assert.async();
+ var fetchDone = assert.async();
+ var cachedFetchDone = assert.async();
+
+ var smwApi = new smw.api();
+ var startDate;
+
+ // Ajax
+ var queryString = '[[Modification date::+]]|?Modification date|?Modification date|?Modification date|limit=100';
+
+ startDate = new Date();
+
+ $.ajax( {
+ url: mw.util.wikiScript( 'api' ),
+ dataType: 'json',
+ data: {
+ 'action': 'ask',
+ 'format': 'json',
+ 'query' : queryString
+ }
+ } )
+ .done( function ( results ) {
+ assert.ok( results, 'Fetch ' + results.query.meta.count + ' items using $.ajax which took: ' + ( new Date().getTime() - startDate.getTime() ) + ' ms' );
+ startDate = new Date();
+ ajaxDone();
+ } );
+
+ smwApi.fetch( queryString )
+ .done( function ( results ) {
+ assert.ok( results, 'Fetch ' + results.query.meta.count + ' items using smw.Api.fetch() which took: ' + ( new Date().getTime() - startDate.getTime() ) + ' ms' );
+ fetchDone();
+ } );
+
+ smwApi.fetch( queryString, true )
+ .done( function ( results ) {
+ assert.ok( results, 'Fetch ' + results.query.meta.count + ' items using smw.Api.fetch() which were cached and took: ' + ( new Date().getTime() - startDate.getTime() ) + ' ms' );
+ cachedFetchDone();
+ } );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.data.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.data.test.js
new file mode 100644
index 00000000..634dc34e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.data.test.js
@@ -0,0 +1,333 @@
+/**
+ * This file is part of the Semantic MediaWiki QUnit test suite
+ * @see https://semantic-mediawiki.org/wiki/QUnit
+ *
+ * @section LICENSE
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ignore
+ *
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * Tests methods provided by ext.smw.data.js
+ * @ignore
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.Data', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+ var testString = '{\"query\":{\"result\":{\"printrequests\":[{\"label\":\"\",\"typeid\":\"_wpg\",\"mode\":2},{\"label\":\"Has test date\",\"typeid\":\"_dat\",\"mode\":1},{\"label\":\"Has test page\",\"typeid\":\"_wpg\",\"mode\":1},{\"label\":\"Has test string\",\"typeid\":\"_str\",\"mode\":1},{\"label\":\"Has test text\",\"typeid\":\"_txt\",\"mode\":1},{\"label\":\"Has test url\",\"typeid\":\"_uri\",\"mode\":1}],\"results\":{\"DataitemFactory\\/1\":{\"printouts\":{\"Has test date\":[\"947548800\"],\"Has test page\":[{\"fulltext\":\"File:FooBarfoo.png\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/File:FooBarfoo.png\",\"namespace\":6},{\"fulltext\":\"Foo page\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/Foo_page\",\"namespace\":0}],\"Has test string\":[\"Foobar string\"],\"Has test text\":[\"foo foo string\"],\"Has test url\":[\"http:\\/\\/localhost\\/mw\\/foobarfoo\"]},\"fulltext\":\"DataitemFactory\\/1\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/DataitemFactory\\/1\",\"namespace\":0},\"DataitemFactory\\/2\":{\"printouts\":{\"Has test date\":[\"1010707200\"],\"Has test page\":[{\"fulltext\":\"File:Foo.png\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/File:Foo.png\",\"namespace\":6},{\"fulltext\":\"Bar page\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/Bar_page\",\"namespace\":0}],\"Has test string\":[\"foo string\"],\"Has test text\":[\"fooBar string\"],\"Has test url\":[\"http:\\/\\/localhost\\/mw\\/foo\"]},\"fulltext\":\"DataitemFactory\\/2\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/DataitemFactory\\/2\",\"namespace\":0},\"DataitemFactory\\/3\":{\"printouts\":{\"Has test date\":[\"1010725200\"],\"Has test page\":[{\"fulltext\":\"Foo page\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/Foo_page\",\"namespace\":0},{\"fulltext\":\"File:FooBar.png\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/File:FooBar.png\",\"namespace\":6}],\"Has test string\":[\"bar string\"],\"Has test text\":[\"fooBar foo string\"],\"Has test url\":[\"http:\\/\\/localhost\\/index.php?title=foo\"]},\"fulltext\":\"DataitemFactory\\/3\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/DataitemFactory\\/3\",\"namespace\":0}},\"meta\":{\"hash\":\"c26caabe31af28817c3f87f26cfd0a3d\",\"count\":3,\"offset\":0}},\"ask\":{\"conditions\":\"[[Has test string::+]]\",\"parameters\":{\"limit\":50,\"offset\":0,\"format\":\"datatables\",\"link\":\"all\",\"headers\":\"show\",\"mainlabel\":\"\",\"intro\":\"\",\"outro\":\"\",\"searchlabel\":\"\\u2026 further results\",\"default\":\"\",\"class\":\"\",\"theme\":\"bootstrap\"},\"printouts\":[\"?Has test date\",\"?Has test page\",\"?Has test string\",\"?Has test text\",\"?Has test url\"]}},\"version\":\"0.1\"}';
+ var subjectLessResult = '{\"query\":{\"result\":{\"printrequests\":[{\"label\":\"Modification date\",\"typeid\":\"_dat\",\"mode\":1}],\"results\":{\"Concepttest3\":{\"printouts\":{\"Modification date\":[\"1358906761\"]}},\"Concepttest4\":{\"printouts\":{\"Modification date\":[\"1358905485\"]}},\"Category:Concepts\":{\"printouts\":{\"Modification date\":[\"1358896550\"]}}},\"meta\":{\"hash\":\"8c727bd6aa52f47caa39bd0c1b93ee59\",\"count\":3,\"offset\":0}},\"ask\":{\"conditions\":\"[[Modification date::+]]\",\"parameters\":{\"limit\":3,\"offset\":0,\"format\":\"datatables\",\"link\":\"all\",\"headers\":\"show\",\"mainlabel\":\"-\",\"intro\":\"\",\"outro\":\"\",\"searchlabel\":\"\\u2026 further results\",\"default\":\"\",\"class\":\"\",\"theme\":\"bootstrap\"},\"printouts\":[\"?Modification date\"]}},\"version\":\"0.1\"}';
+ var unknownType = '{\"query\":{\"result\":{\"printrequests\":[{\"label\":\"\",\"typeid\":\"_wpg\",\"mode\":2},{\"label\":\"Has description\",\"typeid\":\"_foo\",\"mode\":1}],\"results\":{\"File:IMG0027040123.jpg\":{\"printouts\":{\"Has description\":[\"Mauris pellentesque aliquet leo Nam nibh metus facilisi et sem laoreet. Netus ipsum montes et a neque in pulvinar nibh\",\"Facilisi et sem laoreet. Netus ipsum montes et a neque in pulvinar nibh\"]},\"fulltext\":\"File:IMG0027040123.jpg\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/File:IMG0027040123.jpg\",\"namespace\":6}},\"meta\":{\"hash\":\"a116c98703f48d231ec4c8eaee4038f8\",\"count\":1,\"offset\":0}},\"ask\":{\"conditions\":\"[[Has description::+]]\",\"parameters\":{\"limit\":1,\"offset\":0,\"link\":\"all\",\"headers\":\"show\",\"mainlabel\":\"\",\"intro\":\"\",\"outro\":\"\",\"searchlabel\":\"\\u2026 further results\",\"default\":\"\"},\"printouts\":[\"?Has description\"]}},\"version\":\"0.1\"}';
+ var numberType = '{\"query\":{\"result\":{\"printrequests\":[{\"label\":\"\",\"typeid\":\"_wpg\",\"mode\":2},{\"label\":\"Has number\",\"typeid\":\"_num\",\"mode\":1}],\"results\":{\"Image\\/1\":{\"printouts\":{\"Has number\":[1220,1320,99]},\"fulltext\":\"Image\\/1\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/Image\\/1\",\"namespace\":0,\"exists\":true}},\"meta\":{\"hash\":\"c2aa1dc43849ad148c9649e818eeb29b\",\"count\":1,\"offset\":0}},\"ask\":{\"conditions\":\"[[has number::+]]\",\"parameters\":{\"limit\":50,\"offset\":0,\"format\":\"datatables\",\"link\":\"all\",\"headers\":\"show\",\"mainlabel\":\"\",\"intro\":\"\",\"outro\":\"\",\"searchlabel\":\"\\u2026 further results\",\"default\":\"\",\"class\":\"\",\"theme\":\"bootstrap\"},\"printouts\":[\"?Has number\"]}},\"version\":\"0.1\"}';
+ var quantityType = '{\"query\":{\"result\":{\"printrequests\":[{\"label\":\"\",\"typeid\":\"_wpg\",\"mode\":2},{\"label\":\"Area\",\"typeid\":\"_qty\",\"mode\":1}],\"results\":{\"Berlin\":{\"printouts\":{\"Area\":[{\"value\":891.85,\"unit\":\"km\\u00b2\"}]},\"fulltext\":\"Berlin\",\"fullurl\":\"http:\\/\\/localhost\\/mw\\/index.php\\/Berlin\",\"namespace\":0,\"exists\":true}},\"meta\":{\"hash\":\"f0f072f414c3e814c847aff1ba87dfb3\",\"count\":1,\"offset\":0}},\"ask\":{\"conditions\":\"[[Area::+]]\",\"parameters\":{\"limit\":50,\"offset\":0,\"format\":\"datatables\",\"link\":\"all\",\"headers\":\"show\",\"mainlabel\":\"\",\"intro\":\"\",\"outro\":\"\",\"searchlabel\":\"\\u2026 further results\",\"default\":\"\",\"class\":\"\",\"theme\":\"bootstrap\"},\"printouts\":[\"?Area\"]}},\"version\":\"0.2.5\"}';
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.Data();
+ assert.ok( result instanceof Object, pass + 'the smw.dataItem instance was accessible' );
+
+ } );
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'comparison $.parseJSON() vs. smw.Api.parse()', function ( assert ) {
+ assert.expect( 2 );
+
+ var result;
+ var startDate;
+ var smwApi = new smw.Api();
+
+ startDate = new Date();
+ result = $.parseJSON( testString );
+ assert.ok( result, 'Using parseJSON took: ' + ( new Date().getTime() - startDate.getTime() ) + ' ms' );
+
+ startDate = new Date();
+ result = smwApi.parse( testString );
+ assert.ok( result, 'using smw.Api.parse took: ' + ( new Date().getTime() - startDate.getTime() ) + ' ms' );
+
+ } );
+
+ /**
+ * Test smw.dataItem.property factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.property factory test', function ( assert ) {
+ assert.expect( 5 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( testString );
+
+ $.map ( result.query.result.results['DataitemFactory/1'].printouts, function( value, key ) {
+ if ( value instanceof smw.dataItem.property ){
+ assert.equal( value.getLabel(), key , pass + 'the parser returned ' + key );
+ }
+ } );
+
+ } );
+
+ /**
+ * Test subject less
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.property subject less factory test', function ( assert ) {
+ assert.expect( 3 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( subjectLessResult );
+
+ $.map ( result.query.result.results, function( printouts, head ) {
+ $.map ( printouts, function( values ) {
+ $.map ( values, function( value, key ) {
+ if ( value instanceof smw.dataItem.property ){
+ assert.equal( value.getLabel(), key , pass + 'the parser returned ' + key + ' for ' + head );
+ }
+ } );
+ } );
+ } );
+
+ } );
+
+ /**
+ * Test smw.dataItem.wikiPage factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.wikiPage subject factory test', function ( assert ) {
+ assert.expect( 3 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( testString );
+
+ assert.ok( result.query.result.results['DataitemFactory/1'] instanceof smw.dataItem.wikiPage, pass + 'the parser returned a smw.dataItem.wikiPage object' );
+ assert.equal( result.query.result.results['DataitemFactory/1'].getHtml(), 'DataitemFactory/1', pass + 'the object method .getHtml() was accessible' );
+ assert.equal( result.query.result.results['DataitemFactory/1'].getUri(), 'http://localhost/mw/index.php/DataitemFactory/1', pass + 'the object method .getUri() was accessible' );
+
+ } );
+
+ /**
+ * Test smw.dataItem.wikiPage factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.wikiPage multiValue factory test', function ( assert ) {
+ assert.expect( 4 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( testString );
+
+ var expectedMultiValue = ['File:FooBarfoo.png', 'Foo page'];
+
+ $.map ( result.query.result.results['DataitemFactory/1'].printouts, function( values ) {
+ if ( values instanceof smw.dataItem.property ){
+ $.map ( values, function( value, key ) {
+ if ( value instanceof smw.dataItem.wikiPage ){
+ assert.ok( value instanceof smw.dataItem.wikiPage, pass + 'the parser returned a smw.dataItem.wikiPage object' );
+ assert.equal( value.getHtml(), expectedMultiValue[key] , pass + 'the parser returned ' + expectedMultiValue[key] );
+ }
+ } );
+ }
+ } );
+
+ } );
+
+ /**
+ * Test smw.dataItem.time factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.time factory', function ( assert ) {
+ assert.expect( 4 );
+
+ // Use as helper to fetch language dep. month name
+ var monthNames = [];
+ $.map ( mw.config.get( 'wgMonthNames' ), function( value ) {
+ if( value !== '' ){
+ monthNames.push( value );
+ }
+ } );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( testString );
+
+ $.map ( result.query.result.results['DataitemFactory/1'].printouts, function( values ) {
+ if ( values instanceof smw.dataItem.property ){
+ $.map ( values, function( value ) {
+ if ( value instanceof smw.dataItem.time ){
+ assert.ok( value instanceof smw.dataItem.time, pass + 'the parser returned a smw.dataItem.time object' );
+ assert.equal( value.getMediaWikiDate(), '11 ' + monthNames[0] + ' 2000' , pass + 'the parser returned "11 '+ monthNames[0] +' 2000"' );
+ }
+ } );
+ }
+ } );
+
+ $.map ( result.query.result.results['DataitemFactory/3'].printouts, function( values ) {
+ if ( values instanceof smw.dataItem.property ){
+ $.map ( values, function( value ) {
+ if ( value instanceof smw.dataItem.time ){
+ assert.ok( value instanceof smw.dataItem.time, pass + 'the parser returned a smw.dataItem.time object' );
+ assert.equal( value.getMediaWikiDate(), '11 '+ monthNames[0] +' 2002 05:00:00' , pass + 'the parser returned "11 '+ monthNames[0] +' 2002 05:00:00"' );
+ }
+ } );
+ }
+ } );
+
+ } );
+
+ /**
+ * Test smw.dataItem.uri factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.uri factory', function ( assert ) {
+ assert.expect( 4 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( testString );
+
+ $.map ( result.query.result.results['DataitemFactory/2'].printouts, function( values ) {
+ if ( values instanceof smw.dataItem.property ){
+ $.map ( values, function( value ) {
+ if ( value instanceof smw.dataItem.uri ){
+ assert.ok( value instanceof smw.dataItem.uri, pass + 'the parser returned a smw.dataItem.uri object' );
+ assert.equal( value.getUri(), 'http://localhost/mw/foo' , pass + 'getUri() returned "http://localhost/mw/foo"' );
+ assert.equal( value.getHtml( false ), 'http://localhost/mw/foo' , pass + 'getHtml( false ) returned "http://localhost/mw/foo"' );
+ assert.equal( value.getHtml( true ), '<a href=\"http://localhost/mw/foo\">http://localhost/mw/foo</a>' , pass + 'getHtml( true ) returned a href element' );
+ }
+ } );
+ }
+ } );
+ } );
+
+ /**
+ * Test number factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.number factory', function ( assert ) {
+ assert.expect( 3 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( numberType );
+ var expectedNumber = [1220,1320,99];
+ var i=0;
+
+ Object.values( result.query.result.results ).forEach( function ( result ) {
+ Object.values( result.printouts ).forEach( function ( property ) {
+ if ( property instanceof smw.dataItem.property ){
+ $.map ( property, function( value ) {
+ if ( value instanceof smw.dataItem.number ){
+ assert.equal( value.getNumber(), expectedNumber[i] , pass + 'getNumber() returned ' + expectedNumber[i] );
+ i++;
+ }
+ } );
+ }
+ } );
+ } );
+ } );
+
+ /**
+ * Test quantity factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataValue.quantity factory', function ( assert ) {
+ assert.expect( 2 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( quantityType );
+ var expected = { value: 891.85, unit: 'km²' };
+
+ Object.values( result.query.result.results ).forEach( function ( result ) {
+ Object.values( result.printouts ).forEach( function ( property ) {
+ if ( property instanceof smw.dataItem.property ){
+ $.map ( property, function( value ) {
+ if ( value instanceof smw.dataValue.quantity ){
+ assert.equal( value.getValue(), expected.value , pass + 'getValue() returned ' + expected.value );
+ assert.equal( value.getUnit(), expected.unit , pass + 'getUnit() returned ' + expected.unit );
+ }
+ } );
+ }
+ } );
+ } );
+ } );
+
+
+ /**
+ * Test unlisted factory
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'smw.dataItem.unknown factory', function ( assert ) {
+ assert.expect( 4 );
+
+ // Testing indirect via the smw.Api otherwise the whole JSON parsing
+ // needs to be copied
+ var smwApi = new smw.Api();
+ var result = smwApi.parse( unknownType );
+
+ Object.values( result.query.result.results ).forEach( function ( result ) {
+ Object.values( result.printouts ).forEach( function ( property ) {
+ if ( property instanceof smw.dataItem.property ){
+ $.map ( property, function( value ) {
+ if ( value instanceof smw.dataItem.unknown ){
+ assert.ok( value instanceof smw.dataItem.unknown, pass + 'the parser returned a smw.dataItem.unknown object' );
+ assert.equal( value.getDIType(), '_foo' , pass + 'getDIType() returned an unknown type _foo' );
+ }
+ } );
+ }
+ } );
+ } );
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.number.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.number.test.js
new file mode 100644
index 00000000..fe21d062
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.number.test.js
@@ -0,0 +1,73 @@
+/**
+ * QUnit tests
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2 or later
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataItem.number', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ // Data provider
+ var testCases = [
+ { test: [ 1 ], expected: [ 1 ] },
+ { test: [ 0.0001 ], expected: [ 0.0001 ] },
+ { test: [ 1000 ], expected: [ 1000 ] }
+ ];
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 2 );
+
+ var result = new smw.dataItem.number( 3 );
+ assert.ok( result instanceof Object, pass + 'the smw.dataItem.number instance was accessible' );
+
+ assert.throws( function() {
+ new smw.dataItem.number( 'foo' );
+ }, pass + 'an error was raised due to wrong type' );
+
+ } );
+
+ /**
+ * Test type
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDIType', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.number( 3 );
+ assert.equal( result.getDIType(), '_num', pass + 'returned _num' );
+
+ } );
+
+ /**
+ * Test getNumber
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getNumber', function ( assert ) {
+ assert.expect( 3 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.number( testCase.test[0] );
+ assert.equal( result.getNumber(), testCase.expected[0] , pass + 'returned ' + testCase.expected[0] );
+ } );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.property.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.property.test.js
new file mode 100644
index 00000000..944533e9
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.property.test.js
@@ -0,0 +1,60 @@
+/**
+ * QUnit tests
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2 or later
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataItem.property', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.property( 'Has test' );
+ assert.ok( result instanceof Object, pass + 'the smw.dataItem.property instance was accessible' );
+
+ } );
+
+ /**
+ * Test getLabel
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getLabel', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.property( 'Has test' );
+ assert.equal( result.getLabel(), 'Has test', pass + 'a label was returned' );
+
+ } );
+
+ /**
+ * Test getHtml
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getHtml', function ( assert ) {
+ assert.expect( 2 );
+
+ var result = new smw.dataItem.property( 'Has type' );
+ var href = mw.util.wikiGetlink( 'Property:');
+ assert.equal( result.getHtml(), 'Has type', pass + 'a text label was returned' );
+ assert.equal( result.getHtml( true ), '<a href=\"' + href + 'Has_type\">Has type</a>', pass + 'a href link was returned' );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.text.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.text.test.js
new file mode 100644
index 00000000..70a1f02a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.text.test.js
@@ -0,0 +1,80 @@
+/**
+ * QUnit tests
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2 or later
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataItem.text', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 4 );
+
+ var result = new smw.dataItem.text( 'foo' );
+ assert.ok( result instanceof Object, pass + 'the smw.dataItem.text instance was accessible' );
+
+ assert.throws( function() {
+ new smw.dataItem.text( {} );
+ }, pass + 'an error was raised due to the wrong type' );
+
+ assert.throws( function() {
+ new smw.dataItem.text( [] );
+ }, pass + 'an error was raised due to the wrong type' );
+
+ assert.throws( function() {
+ new smw.dataItem.text( 3 );
+ }, pass + 'an error was raised due to the wrong type' );
+
+ } );
+
+ /**
+ * Test type
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDIType', function ( assert ) {
+ assert.expect( 2 );
+
+ var result;
+
+ result = new smw.dataItem.text( 'foo' );
+ assert.equal( result.getDIType(), '_txt', pass + 'getDIType() returned _txt' );
+
+ result = new smw.dataItem.text( 'bar', '_str' );
+ assert.equal( result.getDIType(), '_str', pass + 'getDIType() returned _str' );
+
+ } );
+
+ /**
+ * Test getText
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getText', function ( assert ) {
+ assert.expect( 2 );
+
+ var result;
+
+ var testString = 'Lorem ipsum dolor sit ...';
+
+ result = new smw.dataItem.text( testString );
+ assert.equal( result.getText(), testString, pass + 'getText() returned ' + testString );
+ assert.equal( result.getString(), testString, pass + 'getString() returned ' + testString );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.time.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.time.test.js
new file mode 100644
index 00000000..cf0f0aed
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.time.test.js
@@ -0,0 +1,131 @@
+/**
+ * QUnit tests
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2 or later
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataItem.time', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.time( '1362200400' );
+ assert.ok( result instanceof Object, pass + 'the smw.dataItem.time instance was accessible' );
+
+ } );
+
+ /**
+ * Test type
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDIType', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.time( '1362200400' );
+ assert.equal( result.getDIType(), '_dat', pass + 'returned _dat' );
+
+ } );
+
+ /**
+ * Test getUri
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getMwTimestamp', function ( assert ) {
+ assert.expect( 2 );
+
+ var result;
+
+ result = new smw.dataItem.time( '1362200400' );
+ assert.equal( result.getMwTimestamp(), '1362200400', pass + 'returned a MW timestamp' );
+
+ result = new smw.dataItem.time( 1362200400 );
+ assert.equal( result.getMwTimestamp(), '1362200400', pass + 'returned a MW timestamp' );
+
+ } );
+
+ /**
+ * Test getDate
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDate', function ( assert ) {
+ assert.expect( 1 );
+
+ var result;
+
+ result = new smw.dataItem.time( '1362200400' );
+ assert.ok( result.getDate() instanceof Date, pass + 'returned a JavaScript Date instance' );
+
+ } );
+
+ /**
+ * Test getISO8601Date
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getISO8601Date', function ( assert ) {
+ assert.expect( 1 );
+
+ var result;
+
+ result = new smw.dataItem.time( '1362200400' );
+ assert.equal( result.getISO8601Date(), '2013-03-02T05:00:00.000Z', pass + 'returned a ISO string date/time' );
+
+ } );
+
+ /**
+ * Test getTimeString
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getTimeString', function ( assert ) {
+ assert.expect( 1 );
+
+ var result;
+
+ result = new smw.dataItem.time( '1362200400' );
+ assert.equal( result.getTimeString(), '05:00:00', pass + 'returned a time string' );
+
+ } );
+
+ /**
+ * Test getMediaWikiDate
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getMediaWikiDate', function ( assert ) {
+ assert.expect( 1 );
+
+ var result;
+
+ // Use as helper to fetch language dep. month name
+ var monthNames = [];
+ $.map ( mw.config.get( 'wgMonthNames' ), function( index ) {
+ if( index !== '' ){
+ monthNames.push( index );
+ }
+ } );
+
+ result = new smw.dataItem.time( '1362200400' );
+ assert.equal( result.getMediaWikiDate(), '2 ' + monthNames[2] + ' 2013 05:00:00', pass + 'returned a MW date and time formatted string' );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) ); \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.unknown.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.unknown.test.js
new file mode 100644
index 00000000..99a0fb00
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.unknown.test.js
@@ -0,0 +1,68 @@
+/**
+ * QUnit tests
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2 or later
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataItem.unknown', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ // Data provider
+ var testCases = [
+ { test: [ '' ], expected: [ null, null ] } ,
+ { test: [ 'Foo', '_fooBar' ], expected: [ 'Foo', '_fooBar' ] }
+ ];
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.unknown( 'foo', '_bar' );
+ assert.ok( result instanceof Object, pass + 'the smw.dataItem.unknown instance was accessible' );
+
+ } );
+
+ /**
+ * Test type
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDIType', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.unknown( 'foo', '_bar' );
+ assert.equal( result.getDIType(), '_bar', pass + 'returned "_bar"' );
+
+ } );
+
+ /**
+ * Test getValue
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getValue', function ( assert ) {
+ assert.expect( 2 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.unknown( testCase.test[0], testCase.test[1] );
+ assert.equal( result.getValue(), testCase.expected[0] , pass + 'returned ' + testCase.expected[0] );
+ } );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) ); \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.uri.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.uri.test.js
new file mode 100644
index 00000000..b8dce290
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.uri.test.js
@@ -0,0 +1,90 @@
+/**
+ * QUnit tests
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2 or later
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataItem.uri', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ // Data provider
+ var testCases = [
+ { test: [ '' ], expected: [ null, null ] } ,
+ { test: [ 'http://fooBar/test' ], expected: [ 'http://fooBar/test', '<a href=\"http://fooBar/test\">http://fooBar/test</a>' ] }
+ ];
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.uri( 'http://foo.com/test/' );
+ assert.ok( result instanceof Object, pass + 'the smw.dataItem.uri instance was accessible' );
+
+ } );
+
+ /**
+ * Test type
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDIType', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.uri( 'http://foo.com/test/' );
+ assert.equal( result.getDIType(), '_uri', pass + 'returned _uri' );
+
+ } );
+
+ /**
+ * Test getUri
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getUri', function ( assert ) {
+ assert.expect( 2 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.uri( testCase.test[0] );
+ assert.equal( result.getUri(), testCase.expected[0] , pass + 'returned ' + testCase.expected[0] );
+ } );
+
+ } );
+
+ /**
+ * Test getHtml
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getHtml', function ( assert ) {
+ assert.expect( 4 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.uri( testCase.test[0] );
+ assert.equal( result.getHtml(), testCase.expected[0] , pass + 'returned ' + testCase.expected[0] );
+ } );
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.uri( testCase.test[0] );
+ assert.equal( result.getHtml( true ), testCase.expected[1] , pass + 'returned ' + testCase.expected[1] );
+ } );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.wikiPage.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.wikiPage.test.js
new file mode 100644
index 00000000..ad65dbd3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataItem.wikiPage.test.js
@@ -0,0 +1,240 @@
+/*!
+ * This file is part of the Semantic MediaWiki QUnit test suite
+ * @see https://semantic-mediawiki.org/wiki/QUnit
+ *
+ * @section LICENSE
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * @since 1.9
+ *
+ * @file
+ *
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataItem.wikiPage', QUnit.newMwEnvironment() );
+
+ // Data provider
+ var testCases = [
+ {
+ test: [ '', '', '' ],
+ expected: { 'name': null, 'text': null, 'uri': null, 'ns': 0, 'html': null, 'known': true }
+ } ,
+ {
+ test: [ 'foo', '', '' ],
+ expected: { 'name': 'foo', 'text': 'foo', 'uri': null, 'ns': 0, 'html': 'foo', 'known': true }
+ },
+ {
+ test: [ 'bar', '', 6 ],
+ expected: { 'name': 'bar', 'text': 'bar', 'uri': null, 'ns': 6, 'html': 'bar', 'known': true }
+ },
+ {
+ test: [ 'bar', '', 0, true ],
+ expected: { 'name': 'bar', 'text': 'bar', 'uri': null, 'ns': 0, 'html': 'bar', 'known': true }
+ },
+ {
+ test: [ 'bar', '', 2, false ],
+ expected: { 'name': 'bar', 'text': 'bar', 'uri': null, 'ns': 2, 'html': 'bar', 'known': false }
+ },
+ {
+ test: [ 'fooBar', 'http://fooBar', 0, false ],
+ expected: { 'name': 'fooBar', 'text': 'fooBar', 'uri': 'http://fooBar', 'ns': 0, 'html': '<a href=\"http://fooBar\" class=\"new\">fooBar</a>', 'known': false }
+ },
+ {
+ test: [ 'fooBar#_9a0c8abb8ef729b5c7', 'http://fooBar#_9a0c8abb8ef729b5c7', 0, false ],
+ expected: { 'name': 'fooBar#_9a0c8abb8ef729b5c7', 'text': 'fooBar', 'uri': 'http://fooBar#_9a0c8abb8ef729b5c7', 'ns': 0, 'html': '<a href=\"http://fooBar#_9a0c8abb8ef729b5c7\" class=\"new\">fooBar</a>', 'known': false }
+ },
+ {
+ test: [ 'fooBar', 'http://fooBar', 0, true ],
+ expected: { 'name': 'fooBar', 'text': 'fooBar', 'uri': 'http://fooBar', 'ns': 0, 'html': '<a href=\"http://fooBar\">fooBar</a>', 'known': true }
+ },
+ {
+ test: [ 'Foo#_QUERY9a665a578eb95c1', 'http://Foo#_QUERY9a665a578eb95c1', 0, true ],
+ expected: { 'name': 'Foo#_QUERY9a665a578eb95c1', 'text': 'Foo', 'uri': 'http://Foo#_QUERY9a665a578eb95c1', 'ns': 0, 'html': '<a href=\"http://Foo#_QUERY9a665a578eb95c1\">Foo</a>', 'known': true }
+ },
+ {
+ test: [ 'Foo#_QUERY#9a665a578eb95c1', 'http://Foo#_QUERY#9a665a578eb95c1', 0, true ],
+ expected: { 'name': 'Foo#_QUERY#9a665a578eb95c1', 'text': 'Foo', 'uri': 'http://Foo#_QUERY#9a665a578eb95c1', 'ns': 0, 'html': '<a href=\"http://Foo#_QUERY#9a665a578eb95c1\">Foo</a>', 'known': true }
+ }
+ ];
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.wikiPage( 'foo', 'bar' );
+ assert.ok( result instanceof Object, 'the smw.dataItem.wikiPage instance was accessible' );
+
+ } );
+
+ /**
+ * Test type
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDIType', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataItem.wikiPage( 'foo', 'bar' );
+ assert.equal( result.getDIType(), '_wpg', 'returned _wpg' );
+
+ } );
+
+ /**
+ * Test getPrefixedText
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getPrefixedText', function ( assert ) {
+ assert.expect( 10 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.wikiPage( testCase.test[0], testCase.test[1], testCase.test[2] );
+ assert.equal( result.getPrefixedText(), testCase.expected.name , 'returned ' + testCase.expected.name );
+ } );
+
+ } );
+
+ /**
+ * Test getText
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getText', function ( assert ) {
+ assert.expect( 10 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.wikiPage( testCase.test[0], testCase.test[1], testCase.test[2] );
+ assert.equal( result.getText(), testCase.expected.text , 'returned ' + testCase.expected.text );
+ } );
+
+ } );
+
+ /**
+ * Test getUri
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getUri', function ( assert ) {
+ assert.expect( 10 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.wikiPage( testCase.test[0], testCase.test[1], testCase.test[2] );
+ assert.equal( result.getUri(), testCase.expected.uri , 'returned ' + testCase.expected.uri );
+ } );
+
+ } );
+
+ /**
+ * Test getNamespaceId
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getNamespaceId', function ( assert ) {
+ assert.expect( 10 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.wikiPage( testCase.test[0], testCase.test[1], testCase.test[2] );
+ assert.equal( result.getNamespaceId(), testCase.expected.ns , 'returned ' + testCase.expected.ns );
+ } );
+
+ } );
+
+ /**
+ * Test getTitle
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getTitle', function ( assert ) {
+ assert.expect( 2 );
+
+ var wikiPage = new smw.dataItem.wikiPage( 'File:foo', 'bar' );
+ var title = new mw.Title( 'File:foo' );
+
+ assert.ok( wikiPage.getTitle() instanceof mw.Title, '.getTitle() returned a Title instance' );
+ assert.deepEqual( wikiPage.getTitle(), title, 'returned a Title instance' );
+
+ } );
+
+ /**
+ * Test isKnown
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'isKnown', function ( assert ) {
+ assert.expect( 10 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.wikiPage( testCase.test[0], testCase.test[1], testCase.test[2], testCase.test[3] );
+ assert.equal( result.isKnown(), testCase.expected.known, 'returned ' + testCase.expected.known );
+ } );
+
+ } );
+
+ /**
+ * Test getHtml
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getHtml( false )', function ( assert ) {
+ assert.expect( 10 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.wikiPage( testCase.test[0], testCase.test[1], testCase.test[2] );
+ assert.equal( result.getHtml( false ), testCase.expected.text, 'returned ' + testCase.expected.text );
+ } );
+
+ } );
+
+ /**
+ * Test getHtml
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getHtml( true )', function ( assert ) {
+ assert.expect( 10 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataItem.wikiPage( testCase.test[0], testCase.test[1], testCase.test[2], testCase.test[3] );
+ assert.equal( result.getHtml( true ), testCase.expected.html, 'returned ' + testCase.expected.html );
+ } );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataValue.quantity.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataValue.quantity.test.js
new file mode 100644
index 00000000..f37c6c75
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/data/ext.smw.dataValue.quantity.test.js
@@ -0,0 +1,90 @@
+/**
+ * QUnit tests
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2 or later
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.dataValue.quantity', QUnit.newMwEnvironment() );
+
+ var pass = 'Passes because ';
+
+ // Data provider
+ var testCases = [
+ { test: { value: 1 }, expected: { value: 1 } },
+ { test: { value: 0.0001, unit: 'km²' }, expected: { value: 0.0001, unit: 'km²' } },
+ { test: { value: 1000, unit: 'm²' }, expected: { value: 1000, unit: 'm²' } }
+ ];
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 2 );
+
+ var result = new smw.dataValue.quantity( 3 );
+ assert.ok( result instanceof Object, pass + 'the smw.dataValue.quantity instance was accessible' );
+
+ assert.throws( function() {
+ new smw.dataValue.quantity( 'foo' );
+ }, pass + 'an error was raised due to wrong type' );
+
+ } );
+
+ /**
+ * Test type
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getDIType', function ( assert ) {
+ assert.expect( 1 );
+
+ var result = new smw.dataValue.quantity( 3 );
+ assert.equal( result.getDIType(), '_qty', pass + 'returned _qty' );
+
+ } );
+
+ /**
+ * Test getValue
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getValue', function ( assert ) {
+ assert.expect( 3 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataValue.quantity( testCase.test.value, testCase.test.unit );
+ assert.equal( result.getValue(), testCase.expected.value , pass + 'returned ' + testCase.expected.value );
+ } );
+
+ } );
+
+ /**
+ * Test getUnit
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'getUnit', function ( assert ) {
+ assert.expect( 3 );
+
+ var result;
+
+ $.map( testCases, function ( testCase ) {
+ result = new smw.dataValue.quantity( testCase.test.value, testCase.test.unit );
+ assert.equal( result.getUnit(), testCase.expected.unit , pass + 'returned ' + testCase.expected.unit );
+ } );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/ext.smw.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/ext.smw.test.js
new file mode 100644
index 00000000..68e5d304
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/ext.smw.test.js
@@ -0,0 +1,216 @@
+/*!
+ * This file is part of the Semantic MediaWiki QUnit test suite
+ * @see https://semantic-mediawiki.org/wiki/QUnit
+ *
+ * @section LICENSE
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ *
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw', QUnit.newMwEnvironment() );
+
+ /**
+ * Test initialization and accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'init', function ( assert ) {
+ assert.expect( 17 );
+
+ assert.ok( smw instanceof Object, 'the smw instance was accessible' );
+
+ assert.equal( $.type( smw.log ), 'function', '.log() was accessible' );
+ assert.equal( $.type( smw.msg ), 'function','.msg() was accessible' );
+ assert.equal( $.type( smw.debug ), 'function', '.debug() was accessible' );
+ assert.equal( $.type( smw.version ), 'function', '.version() was accessible' );
+
+ assert.equal( $.type( smw.settings.getList ), 'function', '.settings.getList() was accessible' );
+ assert.equal( $.type( smw.settings.get ), 'function', '.settings.get() was accessible' );
+
+ assert.equal( $.type( smw.formats.getName ), 'function', '.formats.getName() was accessible' );
+ assert.equal( $.type( smw.formats.getList ), 'function', '.formats.getList() was accessible' );
+
+ assert.equal( $.type( smw.async.isEnabled ), 'function', '.async.isEnabled() was accessible' );
+ assert.equal( $.type( smw.async.load ), 'function', '.async.load() was accessible' );
+
+ assert.equal( $.type( smw.util.clean ), 'function', '.util.clean() was accessible' );
+ assert.equal( $.type( smw.util.ucFirst ), 'function', '.util.ucFirst() was accessible' );
+ assert.equal( $.type( smw.util.namespace ), 'object', '.util.namespace object was accessible' );
+ assert.equal( $.type( smw.util.namespace.getList ), 'function', '.util.namespace.getList() was accessible' );
+ assert.equal( $.type( smw.util.namespace.getId ), 'function', '.util.namespace.getId() was accessible' );
+ assert.equal( $.type( smw.util.namespace.getName ), 'function', '.util.namespace.getName() was accessible' );
+
+ } );
+
+ /**
+ * Test settings function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'settings', function ( assert ) {
+ assert.expect( 4 );
+
+ assert.equal( $.type( smw.settings.getList() ), 'object', '.getList() returned a list of settings object' );
+ assert.equal( $.type( smw.settings.get( 'smwgQMaxLimit' ) ), 'number', '.get( "smwgQMaxLimit" ) returned a value for the key' );
+ assert.equal( smw.settings.get( 'lula' ), undefined, '.get( "lula" ) returned undefined for an unknown key' );
+ assert.equal( smw.settings.get(), undefined, '.get() returned undefined for an empty key' );
+
+ } );
+
+ /**
+ * Test util function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'util', function ( assert ) {
+ assert.expect( 3 );
+
+ assert.equal( smw.util.clean( ' Foo | ; : - < >_= () {} bar ' ), 'Foo_;_:_-__=_()_bar', '.clean() returned a cleaned string' );
+ assert.equal( smw.util.clean( 'Foo | ; : - < >_= () {} bar' ), 'Foo_;_:_-__=_()_bar', '.clean() returned a cleaned string' );
+ assert.equal( smw.util.ucFirst( 'foo Foo bar' ), 'Foo Foo bar', '.ucFirst() returned a capitalized string' );
+
+ } );
+
+ /**
+ * Test namespace function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'util.namespace', function ( assert ) {
+ assert.expect( 7 );
+
+ assert.equal( $.type( smw.util.namespace.getList() ), 'object', '.getList() returned a list of namespaces' );
+
+ assert.equal( $.type( smw.util.namespace.getId( 'property' ) ), 'number', '.getId( "property" ) returned a number' );
+ assert.equal( $.type( smw.util.namespace.getId( 'Property' ) ), 'number', '.getId( "Property" ) returned a number' );
+ assert.equal( $.type( smw.util.namespace.getId( 'concept' ) ), 'number', '.getId( "concept" ) returned a number' );
+ assert.equal( smw.util.namespace.getId( 'lula' ), undefined, '.getId( "lula" ) returned undefined for an unknown key' );
+
+ assert.equal( $.type( smw.util.namespace.getName( 'property' ) ), 'string', '.getName( "property" ) returned a string' );
+ assert.equal( smw.util.namespace.getName( 'lula' ), undefined, '.getName( "lula" ) returned undefined for an unknown key' );
+
+ } );
+
+ /**
+ * Test async function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'async', function ( assert ) {
+ assert.expect( 7 );
+
+ var done = assert.async();
+
+ var context;
+ var argument;
+ var result;
+
+ assert.throws( function() {
+ smw.async.load( context );
+ }, '.async.load() thrown an error because of a missing method callback' );
+
+ var test0 = function() {
+ return $( this ).append( '<span id=test-00></span>' );
+ };
+
+ context = $( '<div id="test-0"></div>', '#qunit-fixture' );
+ result = smw.async.load( context, test0 );
+ assert.ok( context.find( '#' + 'test-00' ), '.async.load() was executed and created an element' );
+
+ var test1 = function( id ) {
+ return $( this ).append( '<span id=' + id + '></span>' );
+ };
+
+ argument = 'lula';
+ context = $( '<div id="test-1"></div>', '#qunit-fixture' );
+ result = smw.async.load( context, test1, argument );
+ assert.ok( context.find( '#' + argument ), '.async.load() was executed and created an element using the invoked argument' );
+
+ var test2 = function( options ) {
+ return $( this ).append( '<span id=' + options.id + '></span>' );
+ };
+
+ argument = { 'id': 'lula-2' };
+ context = $( '<div id="test-2"></div>', '#qunit-fixture' );
+ result = smw.async.load( context, test2, argument );
+ assert.ok( context.find( '#' + argument.id ), '.async.load() was executed and created an element using the invoked argument' );
+
+ argument = 'lala';
+ context = $( '<div id="test-3"></div>', '#qunit-fixture' );
+ result = smw.async.load( context, function( id ) {
+ return $( this ).append( '<span id=' + id + '></span>' );
+ }, argument );
+ assert.ok( context.find( '#' + argument ), '.async.load() was executed and created an element using the invoked argument' );
+
+ // Make sure async plug-in is loaded, iterate, and create some content
+ mw.loader.using( 'jquery.async', function() {
+ context = $( '<div id="test-4"></div>', '#qunit-fixture' );
+ for ( var i = 0; i < 4; i++ ) {
+ argument = 'lila-' + i;
+ smw.async.load( context, test1, argument );
+ }
+
+ assert.ok( smw.async.isEnabled(), '.async.isEnabled() returned true' );
+ assert.ok( context.find( '#' + argument ), '.async.load() was executed and created an element using the invoked argument in async mode' );
+
+ done();
+ } );
+
+ } );
+
+ /**
+ * Test formats function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'formats', function ( assert ) {
+ assert.expect( 7 );
+
+ assert.equal( $.type( smw.formats.getList() ), 'object', '.getList() returned an object' );
+ assert.equal( $.type( smw.formats.getName( 'table' ) ), 'string', '.getName( "table" ) returned a string' );
+ assert.equal( $.type( smw.formats.getName( ' table ' ) ), 'string', '.getName( " table " ) returned a string' );
+ assert.equal( $.type( smw.formats.getName( 'Table' ) ), 'string', '.getName( "Table" ) returned a string' );
+
+ assert.equal( smw.formats.getName( 'lula' ), undefined, '.getName() returned undefined for an unknown key' );
+ assert.equal( smw.formats.getName( 123456 ), undefined, '.getName() returned undefined for an unknown key' );
+ assert.equal( smw.formats.getName(), undefined, '.getName() returned undefined for an empty key' );
+
+ } );
+
+ /**
+ * Test version function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'version', function ( assert ) {
+ assert.expect( 1 );
+
+ assert.equal( $.type( smw.version() ), 'string', '.version() returned a string' );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/query/ext.smw.query.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/query/ext.smw.query.test.js
new file mode 100644
index 00000000..ce0f74bd
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/query/ext.smw.query.test.js
@@ -0,0 +1,213 @@
+/**
+ * This file is part of the Semantic MediaWiki QUnit test suite
+ * @see https://semantic-mediawiki.org/
+ *
+ * @section LICENSE
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ignore
+ *
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * Tests methods provided by ext.smw.query.js
+ * @ignore
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.Query', QUnit.newMwEnvironment() );
+ var jsonString = '{\"conditions\":\"[[Modification date::+]]\",\"parameters\":{\"limit\":10,\"offset\":0,\"link\":\"all\",\"headers\":\"show\",\"mainlabel\":\"\",\"intro\":\"\",\"outro\":\"\",\"searchlabel\":\"\\u2026 further results\",\"default\":\"\",\"class\":\"\"},\"printouts\":[\"?Modification date\"]}';
+
+ var pass = 'Passes because ';
+
+ /**
+ * Test accessibility
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 2 );
+
+ var result;
+
+ result = new smw.api();
+ assert.ok( result instanceof Object, pass + 'the api instance was accessible' );
+
+ result = new smw.query();
+ assert.ok( result instanceof Object, pass + 'the api.query instance was accessible' );
+
+ } );
+
+ /**
+ * Test toString sanity
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'toString sanity test', function ( assert ) {
+ assert.expect( 11 );
+
+ var result;
+
+ assert.throws( function() {
+ new smw.query( '', '' ,'' ).toString();
+ }, pass + 'an error was raised due to missing conditions' );
+
+ assert.throws( function() {
+ new smw.query( [], {} ,'' ).toString();
+ }, pass + 'an error was raised due to missing conditions' );
+
+ assert.throws( function() {
+ new smw.query( [], [] , '[[Modification date::+]]' ).toString();
+ }, pass + 'an error was raised due to parameters being a non object' );
+
+ assert.throws( function() {
+ new smw.query( '', [] , '[[Modification date::+]]' ).toString();
+ }, pass + 'an error was raised due to parameters being a non object' );
+
+ assert.throws( function() {
+ new smw.query( '?Modification date', {'limit' : 10, 'offset': 0 } , '[[Modification date::+]]' ).toString();
+ }, pass + 'an error was raised due to printouts weren\'t empty at first, contained values but those weren\'t of type array' );
+
+ assert.throws( function() {
+ new smw.query( ['?Modification date'], ['limit'], '[[Modification date::+]]' ).toString();
+ }, pass + 'an error was raised due to parameters weren\'t empty at first, contained values but those weren\'t of type object' );
+
+ result = new smw.query( '', '' , ['[[Modification date::+]]'] ).toString();
+ assert.equal( result, '[[Modification date::+]]', pass + '.toString() returned a string' );
+
+ result = new smw.query( [], {} , ['[[Modification date::+]]'] ).toString();
+ assert.equal( result, '[[Modification date::+]]', pass + '.toString() returned a string' );
+
+ result = new smw.query(
+ '',
+ {'limit' : 10, 'offset': 0 } ,
+ '[[Modification date::+]]'
+ ).toString();
+ assert.equal( result, '[[Modification date::+]]|limit=10|offset=0', pass + '(printouts = empty, parameters = object, conditions = array).toString() returned a string,' );
+
+ result = new smw.query(
+ ['?Modification date'],
+ {'limit' : 10, 'offset': 0 } ,
+ '[[Modification date::+]]'
+ ).toString();
+ assert.equal( result, '[[Modification date::+]]|?Modification date|limit=10|offset=0', pass + '(printouts = array, parameters = object, conditions = array).toString() returned a string,' );
+
+ result = new smw.query(
+ ['?Modification date'],
+ {'limit' : 10, 'offset': 0 } ,
+ { foo: '[[Modification date::+]]', bar: '[[Modification date::>2013-04-01]]' }
+ ).toString();
+ assert.equal( result, '[[Modification date::+]][[Modification date::>2013-04-01]]|?Modification date|limit=10|offset=0', pass + '(printouts = array, parameters = object, conditions = object).toString() returned a string,' );
+
+ } );
+
+ /**
+ * Test toString
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'toString Ajax response test', function ( assert ) {
+ assert.expect( 4 );
+
+ var done = assert.async();
+
+ var smwApi = new smw.api();
+ var queryObject = smwApi.parse( jsonString );
+
+ var query = new smw.query ( queryObject.printouts, queryObject.parameters, queryObject.conditions );
+
+ assert.ok( $.type( query.toString() ) === 'string', pass + 'the query is a string' );
+ assert.ok( $.type( query.getQueryString() ) === 'string', pass + 'the function alias returned a string' );
+
+ // Ajax
+ smwApi.fetch( query.toString() )
+ .done( function ( results ) {
+
+ assert.ok( true, pass + 'the query returned with a positive server response' );
+ assert.ok( results instanceof Object, pass + 'the query returned with a result object' );
+
+ done();
+ } );
+
+ } );
+
+ /**
+ * Test getLimit
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'getLimit', function ( assert ) {
+ assert.expect( 1 );
+
+ var smwApi = new smw.api();
+ var queryObject = smwApi.parse( jsonString );
+
+ var query = new smw.query ( queryObject.printouts, queryObject.parameters, queryObject.conditions );
+ assert.equal( query.getLimit(), 10, pass + 'the query limit parameter returned 10' );
+
+ } );
+
+
+ /**
+ * Test getLink
+ *
+ * @since: 1.9
+ * @ignore
+ */
+ QUnit.test( 'getLink', function ( assert ) {
+ assert.expect( 5 );
+
+ var result, context;
+
+ var smwApi = new smw.api();
+ var queryObject = smwApi.parse( jsonString );
+
+ result = new smw.query ( queryObject.printouts, queryObject.parameters, queryObject.conditions ).getLink();
+ assert.equal( $.type( result ), 'string', pass + 'the query link returned was a string' );
+
+ // DOM test
+ context = $( '<div></div>', '#qunit-fixture' );
+ context.append( result );
+ assert.equal( context.find( 'a' ).attr( 'class' ), 'query-link', pass + 'DOM object returned class attribute "query-link"' );
+ assert.ok( context.find( 'a' ).attr( 'href' ), pass + 'DOM object returned a href attribute' );
+
+ // Caption text test
+ context = $( '<div></div>', '#qunit-fixture' );
+ queryObject.parameters.searchlabel = 'test';
+ result = new smw.query ( queryObject.printouts, queryObject.parameters, queryObject.conditions ).getLink();
+ context.append( result );
+ assert.equal( context.find( 'a' ).text( ), 'test', pass + 'parameters.searchlabel is used to set the caption text' );
+
+ context = $( '<div></div>', '#qunit-fixture' );
+ result = new smw.query ( queryObject.printouts, queryObject.parameters, queryObject.conditions ).getLink( 'test 2' );
+ context.append( result );
+ assert.equal( context.find( 'a' ).text( ), 'test 2', pass + 'getLink() is used to set the caption text' );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) );
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/util/ext.smw.util.tooltip.test.js b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/util/ext.smw.util.tooltip.test.js
new file mode 100644
index 00000000..cf7fd922
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/qunit/smw/util/ext.smw.util.tooltip.test.js
@@ -0,0 +1,102 @@
+/*!
+ * This file is part of the Semantic MediaWiki QUnit test suite
+ * @see https://semantic-mediawiki.org/wiki/QUnit
+ *
+ * @section LICENSE
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+( function ( $, mw, smw ) {
+ 'use strict';
+
+ QUnit.module( 'ext.smw.util.tooltip', QUnit.newMwEnvironment() );
+
+ /**
+ * Test initialization and accessibility
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'instance', function ( assert ) {
+ assert.expect( 1 );
+
+ var tooltip = new smw.util.tooltip();
+
+ assert.ok( tooltip instanceof Object, 'smw.util.tooltip instance was accessible' );
+
+ } );
+
+ /**
+ * Test .show() function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'show', function ( assert ) {
+ assert.expect( 2 );
+
+ var tooltip = new smw.util.tooltip();
+ var fixture = $( '#qunit-fixture' );
+
+ assert.equal( $.type( tooltip.show ), 'function', '.show() was accessible' );
+
+ tooltip.show( {
+ context: fixture,
+ content: 'Test',
+ title: 'Test',
+ button: false
+ } );
+
+ assert.ok( fixture.data( 'hasqtip' ), '.data( "hasqtip" ) was accessible' );
+
+ } );
+
+ /**
+ * Test .add() function
+ *
+ * @since: 1.9
+ */
+ QUnit.test( 'add', function ( assert ) {
+ assert.expect( 3 );
+
+ var tooltip = new smw.util.tooltip();
+ var fixture = $( '#qunit-fixture' );
+
+ assert.equal( $.type( tooltip.add ), 'function', '.add() was accessible' );
+
+ tooltip.add( {
+ contextClass: 'test',
+ contentClass: 'test-content',
+ targetClass : 'test-target',
+ context: fixture,
+ content: 'Test 2',
+ title: 'Test 2',
+ type: 'info',
+ button: true
+ } );
+
+ assert.ok( fixture.find( '.test' ), 'created context class' );
+ assert.ok( fixture.data( 'hasqtip' ), '.data( "hasqtip" ) was accessible' );
+
+ } );
+
+}( jQuery, mediaWiki, semanticMediaWiki ) ); \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/README.md b/www/wiki/extensions/SemanticMediaWiki/tests/travis/README.md
new file mode 100644
index 00000000..b8c5c35c
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/README.md
@@ -0,0 +1,57 @@
+- `install-mediawiki.sh` to handle the install of MediaWiki
+- `install-semantic-mediawiki.sh` to handle the install of Semantic MediaWiki
+- `install-services.sh` to handle the install of additional services
+
+## SPARQL endpoints and services
+
+- Fuseki (mem)
+ - Connector: Fuseki (When running integration tests with [Jena Fuseki][fuseki] it is suggested that the `in-memory` option is used to avoid potential loss of production data during test execution.)
+ - QueryEndPoint: http://localhost:3030/db/query
+ - UpdateEndPoint: http://localhost:3030/db/update
+ - DataEndpoint:
+ - DefaultGraph:
+ - Comments: fuseki-server --update --port=3030 --mem /db
+
+- Fuseki (memTDB)
+ - Connector: Fuseki
+ - QueryEndPoint: http://localhost:3030/db/query
+ - UpdateEndPoint: http://localhost:3030/db/update
+ - DataEndpoint:
+ - DefaultGraph: http://example.org/myFusekiGraph
+ - Comments: fuseki-server --update --port=3030 --memTDB --set tdb:unionDefaultGraph=true /db
+
+- Virtuoso opensource
+ - Connector: Virtuoso
+ - QueryEndPoint: http://localhost:8890/sparql
+ - UpdateEndPoint: http://localhost:8890/sparql
+ - DataEndpoint:
+ - DefaultGraph: http://example.org/myVirtuosoGraph
+ - Comments: sudo apt-get install virtuoso-opensource
+
+- 4store
+ - Connector: 4store (Currently, Travis-CI doesn't support `4Store` (1.1.4-2) as service but the following configuration has been successfully tested with the available test suite. ([issue #110](https://github.com/garlik/4store/issues/110))
+ - QueryEndPoint: http://localhost:8088/sparql/
+ - UpdateEndPoint: http://localhost:8088/update/
+ - DataEndpoint:
+ - DefaultGraph: http://example.org/myFourGraph
+ - Comments: apt-get install 4store
+
+- Sesame
+ - Connector: Sesame
+ - QueryEndPoint: http://localhost:8080/openrdf-sesame/repositories/test-smw
+ - UpdateEndPoint: http://localhost:8080/openrdf-sesame/repositories/test-smw/statements
+ - DataEndpoint:
+ - DefaultGraph:
+ - Comments: `test-smw` is specified as native in-memory store
+
+- Blazegraph
+ - Connector: Blazegraph
+ - QueryEndPoint: http://localhost:9999/bigdata/namespace/kb/sparql
+ - UpdateEndPoint: http://localhost:9999/bigdata/namespace/kb/sparql
+ - DataEndpoint:
+ - DefaultGraph:
+ - Comments: java -server -Xmx4g -Dbigdata.propertyFile=$BASE_PATH/tests/travis/blazegraph-store.properties -jar bigdata-bundled.jar
+
+[fuseki]: https://jena.apache.org/
+[virtuoso]: https://github.com/openlink/virtuoso-opensource
+[4store]: https://github.com/garlik/4store
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/blazegraph-store.properties b/www/wiki/extensions/SemanticMediaWiki/tests/travis/blazegraph-store.properties
new file mode 100644
index 00000000..9ff6b1a1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/blazegraph-store.properties
@@ -0,0 +1,53 @@
+# http://sourceforge.net/p/bigdata/git/ci/master/tree/bigdata-war/src/WEB-INF/RWStore.properties
+# Note: These options are applied when the journal and the triple store are
+# first created.
+
+##
+## Journal options.
+##
+
+# The backing file. This contains all your data. You want to put this someplace
+# safe. The default locator will wind up in the directory from which you start
+# your servlet container.
+com.bigdata.journal.AbstractJournal.file=bigdata.jnl
+
+# The persistence engine. Use 'Disk' for the WORM or 'DiskRW' for the RWStore.
+com.bigdata.journal.AbstractJournal.bufferMode=DiskRW
+
+# Setup for the RWStore recycler rather than session protection.
+com.bigdata.service.AbstractTransactionService.minReleaseAge=1
+
+# Enable group commit. See http://wiki.blazegraph.com/wiki/index.php/GroupCommit
+# Note: Group commit is a beta feature in BlazeGraph release 1.5.1.
+#com.bigdata.journal.Journal.groupCommit=true
+
+com.bigdata.btree.writeRetentionQueue.capacity=4000
+com.bigdata.btree.BTree.branchingFactor=128
+
+# 200M initial extent.
+com.bigdata.journal.AbstractJournal.initialExtent=209715200
+com.bigdata.journal.AbstractJournal.maximumExtent=209715200
+
+##
+## Setup for QUADS mode without the full text index.
+##
+com.bigdata.rdf.sail.truthMaintenance=false
+com.bigdata.rdf.store.AbstractTripleStore.quads=true
+com.bigdata.rdf.store.AbstractTripleStore.statementIdentifiers=false
+com.bigdata.rdf.store.AbstractTripleStore.textIndex=false
+com.bigdata.rdf.store.AbstractTripleStore.axiomsClass=com.bigdata.rdf.axioms.NoAxioms
+
+# Bump up the branching factor for the lexicon indices on the default kb.
+com.bigdata.namespace.kb.lex.com.bigdata.btree.BTree.branchingFactor=400
+
+# Bump up the branching factor for the statement indices on the default kb.
+com.bigdata.namespace.kb.spo.com.bigdata.btree.BTree.branchingFactor=1024
+
+# Uncomment to enable collection of OS level performance counters. When
+# collected they will be self-reported through the /counters servlet and
+# the workbench "Performance" tab.
+#
+# com.bigdata.journal.Journal.collectPlatformStatistics=true
+
+# To avoid java.lang.IllegalStateException
+com.bigdata.rdf.store.AbstractTripleStore.inlineDateTimes=false
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-mediawiki.sh b/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-mediawiki.sh
new file mode 100644
index 00000000..33cf08b3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-mediawiki.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+set -ex
+
+cd ..
+
+## Use sha (master@5cc1f1d) to download a particular commit to avoid breakages
+## introduced by MediaWiki core
+if [[ "$MW" == *@* ]]
+then
+ arrMw=(${MW//@/ })
+ MW=${arrMw[0]}
+ SOURCE=${arrMw[1]}
+else
+ MW=$MW
+ SOURCE=$MW
+fi
+
+wget https://github.com/wikimedia/mediawiki/archive/$SOURCE.tar.gz -O $MW.tar.gz
+
+tar -zxf $MW.tar.gz
+mv mediawiki-* mw
+
+cd mw
+
+## MW 1.25 requires Psr\Logger
+if [ -f composer.json ]
+then
+ composer install
+fi
+
+if [ "$DB" == "postgres" ]
+then
+ # See #458
+ sudo /etc/init.d/postgresql stop
+
+ # Travis@support: Try adding a sleep of a few seconds between starting PostgreSQL
+ # and the first command that accesses PostgreSQL
+ sleep 3
+
+ sudo /etc/init.d/postgresql start
+ sleep 3
+
+ psql -c 'create database its_a_mw;' -U postgres
+ php maintenance/install.php --dbtype $DB --dbuser postgres --dbname its_a_mw --pass nyan TravisWiki admin --scriptpath /TravisWiki
+else
+ mysql -e 'create database its_a_mw;'
+ php maintenance/install.php --dbtype $DB --dbuser root --dbname its_a_mw --dbpath $(pwd) --pass nyan TravisWiki admin --scriptpath /TravisWiki
+fi
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-semantic-mediawiki.sh b/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-semantic-mediawiki.sh
new file mode 100644
index 00000000..de369506
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-semantic-mediawiki.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+set -ex
+
+BASE_PATH=$(pwd)
+MW_INSTALL_PATH=$BASE_PATH/../mw
+
+## PHPUnit sources need to be present otherwise the MW testrunner will complain
+## about it
+function installExtrasUsingComposer {
+ if [ "$PHPUNIT" != "" ]
+ then
+ composer require 'phpunit/phpunit='$PHPUNIT --update-with-dependencies
+ else
+ composer require 'phpunit/phpunit=3.7.*' --update-with-dependencies
+ fi
+
+ if [ "$ES" != "" ]
+ then
+ composer require 'elasticsearch/elasticsearch=6.0.*' --update-with-dependencies
+ fi
+}
+
+# Run Composer installation from the MW root directory
+function installSmwIntoMwWithComposer {
+ echo -e "Running MW root composer install build on $TRAVIS_BRANCH \n"
+
+ cd $MW_INSTALL_PATH
+
+ installExtrasUsingComposer
+ composer require mediawiki/semantic-media-wiki "dev-master" --dev
+
+ cd extensions
+ cd SemanticMediaWiki
+
+ # Pull request number, "false" if it's not a pull request
+ # After the install via composer an additional get fetch is carried out to
+ # update th repository to make sure that the latests code changes are
+ # deployed for testing
+ if [ "$TRAVIS_PULL_REQUEST" != "false" ]
+ then
+ git fetch origin +refs/pull/"$TRAVIS_PULL_REQUEST"/merge:
+ git checkout -qf FETCH_HEAD
+ else
+ git fetch origin "$TRAVIS_BRANCH"
+ git checkout -qf FETCH_HEAD
+ fi
+
+ cd ../..
+
+ # Rebuild the class map for added classes during git fetch
+ composer dump-autoload
+}
+
+# Running tarball build only on the master branch to detect other issues before it is merged
+# because the tarball build will not contain the latests submitted version.
+# We do however want to ensure noticing any breakage of this process before we prepare a release.
+function installSmwAsTarballLikeBuild {
+ echo -e "Running tarball build on $TRAVIS_BRANCH \n"
+
+ cd $MW_INSTALL_PATH/extensions
+ composer create-project mediawiki/semantic-media-wiki SemanticMediaWiki dev-master -s dev --prefer-dist --no-dev --no-interaction
+
+ cd SemanticMediaWiki
+ installExtrasUsingComposer
+}
+
+function installSmwByRunningComposerInstallInIt {
+ echo -e "Running composer install build on $TRAVIS_BRANCH \n"
+
+ cp -r $BASE_PATH $MW_INSTALL_PATH/extensions/SemanticMediaWiki
+ cd $MW_INSTALL_PATH/extensions/SemanticMediaWiki
+
+ installExtrasUsingComposer
+ composer install
+}
+
+if [ "$TYPE" == "composer" ]
+then
+ installSmwIntoMwWithComposer
+elif [ "$TYPE" == "relbuild" ] && [ "$TRAVIS_BRANCH" == "master" ]
+then
+ installSmwAsTarballLikeBuild
+else
+ installSmwByRunningComposerInstallInIt
+fi
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-services.sh b/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-services.sh
new file mode 100644
index 00000000..eaba78e5
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/install-services.sh
@@ -0,0 +1,239 @@
+#!/bin/bash
+set -ex
+BASE_PATH=$(pwd)
+E_UNREACHABLE=86
+
+if [ "$FOURSTORE" != "" ] || [ "$VIRTUOSO" != "" ] || [ "$SESAME" != "" ] || [[ "$FUSEKI" == "2."* ]]
+then
+ sudo apt-get update -qq
+fi
+
+# Version 1.1.0 is available and testable on Travis/SMW
+if [ "$FUSEKI" != "" ]
+then
+ # Archive
+ # http://archive.apache.org/dist/jena/binaries/jena-fuseki-$FUSEKI-distribution.tar.gz
+ # http://www.eu.apache.org/dist/jena/binaries/jena-fuseki-$FUSEKI-distribution.tar.gz
+
+ # Avoid ERROR 503: Service Unavailable
+ # wget http://archive.apache.org/dist/jena/binaries/jena-fuseki-$FUSEKI-distribution.tar.gz
+
+ if [[ "$FUSEKI" == "2."* ]]
+ then
+
+ # Fuseki requires Java8 for Fuseki2 v2.3.0 onwards
+ #sudo apt-get install oracle-java8-installer
+
+ #export JAVA_HOME="/usr/lib/jvm/java-8-oracle";
+ #export PATH="$PATH:/usr/lib/jvm/java-8-oracle/bin";
+ #export java_path="/usr/lib/jvm/java-8-oracle/jre/bin/java";
+
+ wget https://github.com/mwjames/travis-support/raw/master/fuseki/$FUSEKI/apache-jena-fuseki-$FUSEKI.tar.gz
+
+ # option z caused "gzip: stdin: not in gzip format"
+ tar -xf apache-jena-fuseki-$FUSEKI.tar.gz
+ mv apache-jena-fuseki-$FUSEKI fuseki
+ else
+ wget https://github.com/mwjames/travis-support/raw/master/fuseki/$FUSEKI/jena-fuseki-$FUSEKI-distribution.tar.gz
+
+ tar -zxf jena-fuseki-$FUSEKI-distribution.tar.gz
+ mv jena-fuseki-$FUSEKI fuseki
+ fi
+
+ cd fuseki
+
+ ## Start fuseki in-memory as background
+ bash fuseki-server --update --mem /db &>/dev/null &
+fi
+
+if [ "$SESAME" != "" ]
+then
+ TOMCAT_VERSION=tomcat6
+ sudo java -version
+
+ sudo apt-get install $TOMCAT_VERSION
+
+ CATALINA_BASE=/var/lib/$TOMCAT_VERSION
+ CATALINA_HOME=/usr/share/$TOMCAT_VERSION
+
+ sudo chown $USER -R $CATALINA_BASE/
+ sudo chmod g+rw -R $CATALINA_BASE/
+
+ sudo mkdir -p $CATALINA_HOME/.aduna
+ sudo chown -R $TOMCAT_VERSION:$TOMCAT_VERSION $CATALINA_HOME
+
+ # One method to get the war files
+ # wget http://search.maven.org/remotecontent?filepath=org/openrdf/sesame/sesame-http-server/$SESAME/sesame-http-server-$SESAME.war -O openrdf-sesame.war
+ # wget http://search.maven.org/remotecontent?filepath=org/openrdf/sesame/sesame-http-workbench/$SESAME/sesame-http-workbench-$SESAME.war -O openrdf-workbench.war
+ # cp *.war /var/lib/tomcat6/webapps/
+
+ # http://sourceforge.net/projects/sesame/
+ # Unreliable sourceforge.net download
+ # wget http://downloads.sourceforge.net/project/sesame/Sesame%202/$SESAME/openrdf-sesame-$SESAME-sdk.zip
+ wget https://github.com/mwjames/travis-support/raw/master/sesame/$SESAME/openrdf-sesame-$SESAME-sdk.zip
+
+ # tar caused a lone zero block, using zip instead
+ unzip -q openrdf-sesame-$SESAME-sdk.zip
+ cp openrdf-sesame-$SESAME/war/*.war $CATALINA_BASE/webapps/
+
+ sudo service $TOMCAT_VERSION restart
+ ps -ef | grep tomcat
+
+ sleep 5
+
+ if curl --output /dev/null --silent --head --fail "http://localhost:8080/openrdf-sesame"
+ #if curl --output /dev/null --silent --head --fail "http://localhost:8080/openrdf-sesame/home/overview.view"
+ then
+ echo "openrdf-sesame service url is reachable"
+ else
+ echo "openrdf-sesame service url is not reachable"
+ sudo cat $CATALINA_BASE/logs/*.log &
+ sudo cat $CATALINA_BASE/logs/catalina.out &
+ exit $E_UNREACHABLE
+ fi
+
+ ./openrdf-sesame-$SESAME/bin/console.sh < $BASE_PATH/tests/travis/openrdf-sesame-memory-repository.txt
+fi
+
+# Version 1.1.4-1 is available but has a problem
+# https://github.com/garlik/4store/issues/110
+# 4STORE can not be used as variable name therefore FOURSTORE
+if [ "$FOURSTORE" != "" ]
+then
+
+ sudo mkdir /var/lib/4store/
+ sudo mkdir /var/lib/4store/db
+ sudo chown $USER -R /var/lib/4store/
+ sudo chmod g+rw -R /var/lib/4store/
+
+ sudo apt-get install 4store=$FOURSTORE
+
+ ## Disabling the firewall
+ sudo iptables -F
+
+ 4s-backend-setup db
+ 4s-backend db
+
+ ## Output the current process table
+ ps auwwx | grep 4s-
+
+ ## -D only used to check the status of the 4store instance
+ ## 4s-httpd -D -p 8088 db
+
+ 4s-httpd -p 8088 db
+fi
+
+# Version 6.1 is available
+if [[ "$VIRTUOSO" == "6."* ]]
+then
+ sudo apt-get install -qq virtuoso-opensource
+ echo "RUN=yes" | sudo tee -a /etc/default/virtuoso-opensource-$VIRTUOSO
+ sudo service virtuoso-opensource-$VIRTUOSO start
+
+ isql-vt 1111 dba dba $BASE_PATH/tests/travis/virtuoso-sparql-permission.sql
+fi
+
+# Version 7 is not available as deb package so we have to build it from scratch
+if [[ "$VIRTUOSO" == "7."* ]]
+then
+ sudo apt-get install libssl-dev -q
+ sudo apt-get install autoconf automake bison flex gawk gperf libtool -q
+
+ #git clone git://github.com/openlink/virtuoso-opensource.git
+ #cd virtuoso-opensource
+ #git pull origin stable/7
+ wget --no-check-certificate -q https://github.com/openlink/virtuoso-opensource/archive/v$VIRTUOSO.zip -O virtuoso-opensource.zip
+
+ unzip -q virtuoso-opensource.zip
+ mv virtuoso-opensource-$VIRTUOSO virtuoso-opensource
+
+ cd virtuoso-opensource
+ ./autogen.sh
+
+ # --disable-all-vads: This parameter disables building all the VAD packages (tutorials, demos, etc.).
+ # --with-readline: This parameter is used so that the system Readline library is used
+ # --program-transform-name: Both Virtuoso and unixODBC install a program named isql. Use this parameter to rename virtuosos program to isql-v
+
+ ./configure --program-transform-name="s/isql/isql-v/" --with-readline --disable-all-vads |& tee #configure.log
+
+ # Only output error and warnings
+ make > /dev/null
+
+ # Build tree to start the automated test suite
+ # make check
+
+ sudo make install
+
+ ## For Virtuoso
+ #export PATH=$PATH:/usr/local/virtuoso-opensource/bin
+
+ sudo /usr/local/virtuoso-opensource/bin/virtuoso-t -f -c /usr/local/virtuoso-opensource/var/lib/virtuoso/db/virtuoso.ini &
+ #sudo /usr/local/virtuoso-opensource/bin/virtuoso-t -f &
+
+ sleep 10
+
+ sudo /usr/local/virtuoso-opensource/bin/isql-v 1111 dba dba $BASE_PATH/tests/travis/virtuoso-sparql-permission.sql
+fi
+
+#@see http://wiki.blazegraph.com/wiki/index.php/NanoSparqlServer
+if [ "$BLAZEGRAPH" != "" ]
+then
+ #sudo apt-get install tomcat6
+
+ #sudo chown $USER -R /var/lib/tomcat6/
+ #sudo chmod g+rw -R /var/lib/tomcat6/
+
+ #sudo mkdir -p /usr/share/tomcat6/.aduna
+ #sudo chown -R tomcat6:tomcat6 /usr/share/tomcat6
+
+ # http://sourceforge.net/projects/bigdata/
+ #wget http://downloads.sourceforge.net/project/bigdata/bigdata/$BLAZEGRAPH/bigdata.war
+
+ #cp bigdata.war /var/lib/tomcat6/webapps/
+ #export JAVA_OPTS="-server -Xmx2g -Dcom.bigdata.rdf.sail.webapp.ConfigParams.propertyFile="$BASE_PATH/tests/travis/blazegraph-store.properties
+
+ #sudo service tomcat6 restart
+ #sleep 3
+
+ #Using the jar
+ # Unreliable sourceforge.net download
+ # wget http://downloads.sourceforge.net/project/bigdata/bigdata/$BLAZEGRAPH/bigdata-bundled.jar
+ wget https://github.com/mwjames/travis-support/raw/master/blazegraph/$BLAZEGRAPH/bigdata-bundled.jar
+
+ java -server -Xmx4g -Dbigdata.propertyFile=$BASE_PATH/tests/travis/blazegraph-store.properties -jar bigdata-bundled.jar &>/dev/null &
+ sleep 5
+
+ if curl --output /dev/null --silent --head --fail "http://localhost:9999/bigdata"
+ then
+ echo "blazegraph service url is reachable"
+ else
+ echo "blazegraph service url is not reachable"
+ exit $E_UNREACHABLE
+ fi
+
+fi
+
+if [ "$ES" != "" ]
+then
+
+ # Configure a specific version of Elasticsearch
+ # See: https://docs.travis-ci.com/user/database-setup/#Installing-ElasticSearch-on-trusty-container-based-infrastructure
+
+ if [[ "$ES" == "5."* ]]
+ then
+
+ sudo apt-get install oracle-java8-installer
+
+ export JAVA_HOME="/usr/lib/jvm/java-8-oracle";
+ export PATH="$PATH:/usr/lib/jvm/java-8-oracle/bin";
+ export java_path="/usr/lib/jvm/java-8-oracle/jre/bin/java";
+
+ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-${ES}.tar.gz
+
+ tar -xzf elasticsearch-${ES}.tar.gz
+ fi
+
+ ./elasticsearch-${ES}/bin/elasticsearch &>/dev/null &
+
+ wget -q --waitretry=1 --retry-connrefused -T 10 -O - http://127.0.0.1:9200
+fi
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/openrdf-sesame-memory-repository.txt b/www/wiki/extensions/SemanticMediaWiki/tests/travis/openrdf-sesame-memory-repository.txt
new file mode 100644
index 00000000..2ce4b63e
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/openrdf-sesame-memory-repository.txt
@@ -0,0 +1,8 @@
+connect http://localhost:8080/openrdf-sesame .
+create memory .
+test-smw
+test store for Semantic MediaWiki
+10000
+true
+120
+quit . \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/run-tests.sh b/www/wiki/extensions/SemanticMediaWiki/tests/travis/run-tests.sh
new file mode 100644
index 00000000..aa194b77
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/run-tests.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+set -ex
+
+BASE_PATH=$(pwd)
+MW_INSTALL_PATH=$BASE_PATH/../mw
+
+cd $MW_INSTALL_PATH/extensions/SemanticMediaWiki
+
+if [ "$TYPE" == "coverage" ]
+then
+ composer phpunit -- --coverage-clover $BASE_PATH/tests/coverage.clover
+elif [ "$TYPE" == "benchmark" ]
+then
+ composer phpunit -- --group semantic-mediawiki-benchmark
+elif [ "$TYPE" == "debug" ]
+then
+ composer phpunit -- --debug-tests
+else
+ composer phpunit
+fi
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/update-configuration-settings.sh b/www/wiki/extensions/SemanticMediaWiki/tests/travis/update-configuration-settings.sh
new file mode 100644
index 00000000..0c871fef
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/update-configuration-settings.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+set -ex
+
+BASE_PATH=$(pwd)
+MW_INSTALL_PATH=$BASE_PATH/../mw
+
+cd $MW_INSTALL_PATH
+
+# Namespace related settings
+echo 'define("NS_TRAVIS", 998);' >> LocalSettings.php
+echo 'define("NS_TRAVIS_TALK", 999);' >> LocalSettings.php
+echo '$wgExtraNamespaces[NS_TRAVIS] = "Travis";' >> LocalSettings.php
+echo '$wgExtraNamespaces[NS_TRAVIS_TALK] = "Travis_talk";' >> LocalSettings.php
+echo '$wgNamespacesWithSubpages[NS_TRAVIS] = true;' >> LocalSettings.php
+
+# echo 'require_once( __DIR__ . "/extensions/SemanticMediaWiki/SemanticMediaWiki.php" );' >> LocalSettings.php
+echo 'wfLoadExtension( "SemanticMediaWiki" );' >> LocalSettings.php
+
+echo '$smwgNamespacesWithSemanticLinks = array( NS_MAIN => true, NS_FILE => true, NS_TRAVIS => true );' >> LocalSettings.php
+echo '$smwgNamespace = "http://example.org/id/";' >> LocalSettings.php
+
+if [ "$FOURSTORE" != "" ]
+then
+ echo '$smwgDefaultStore = "SMWSparqlStore";' >> LocalSettings.php
+ echo '$smwgSparqlRepositoryConnector = "4Store";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["query"] = "http://localhost:8088/sparql/";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["update"] = "http://localhost:8088/update/";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["data"] = "";' >> LocalSettings.php
+ echo '$smwgSparqlDefaultGraph = "http://example.org/mydefaultgraphname";' >> LocalSettings.php
+elif [ "$FUSEKI" != "" ]
+then
+ echo '$smwgDefaultStore = "SMWSparqlStore";' >> LocalSettings.php
+ echo '$smwgSparqlRepositoryConnector = "Fuseki";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["query"] = "http://localhost:3030/db/query";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["update"] = "http://localhost:3030/db/update";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["data"] = "";' >> LocalSettings.php
+elif [ "$SESAME" != "" ]
+then
+ echo '$smwgDefaultStore = "SMWSparqlStore";' >> LocalSettings.php
+ echo '$smwgSparqlRepositoryConnector = "Sesame";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["query"] = "http://localhost:8080/openrdf-sesame/repositories/test-smw";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["update"] = "http://localhost:8080/openrdf-sesame/repositories/test-smw/statements";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["data"] = "";' >> LocalSettings.php
+elif [ "$BLAZEGRAPH" != "" ]
+then
+ echo '$smwgDefaultStore = "SMWSparqlStore";' >> LocalSettings.php
+ echo '$smwgSparqlRepositoryConnector = "Blazegraph";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["query"] = "http://localhost:9999/bigdata/namespace/kb/sparql";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["update"] = "http://localhost:9999/bigdata/namespace/kb/sparql";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["data"] = "";' >> LocalSettings.php
+ echo '$smwgSparqlDefaultGraph = "";' >> LocalSettings.php
+elif [ "$VIRTUOSO" != "" ]
+then
+ echo '$smwgDefaultStore = "SMWSparqlStore";' >> LocalSettings.php
+ echo '$smwgSparqlRepositoryConnector = "Virtuoso";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["query"] = "http://localhost:8890/sparql";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["update"] = "http://localhost:8890/sparql";' >> LocalSettings.php
+ echo '$smwgSparqlEndpoint["data"] = "";' >> LocalSettings.php
+ echo '$smwgSparqlDefaultGraph = "http://example.org/travisGraph";' >> LocalSettings.php
+elif [ "$ES" != "" ]
+then
+ echo '$smwgDefaultStore = "SMWElasticStore";' >> LocalSettings.php
+ echo '$smwgElasticsearchEndpoints = [ "http://127.0.0.1:9200" ];' >> LocalSettings.php
+else
+ echo '$smwgDefaultStore = "SMWSQLStore3";' >> LocalSettings.php
+fi
+
+# Site language
+if [ "$SITELANG" != "" ]
+then
+ echo '$wgLanguageCode = "'$SITELANG'";' >> LocalSettings.php
+fi
+
+# Error reporting
+echo 'error_reporting(E_ALL| E_STRICT);' >> LocalSettings.php
+echo 'ini_set("display_errors", 1);' >> LocalSettings.php
+echo '$wgShowExceptionDetails = true;' >> LocalSettings.php
+echo '$wgDevelopmentWarnings = true;' >> LocalSettings.php
+echo '$wgShowSQLErrors = true;' >> LocalSettings.php
+echo '$wgDebugDumpSql = false;' >> LocalSettings.php
+echo '$wgShowDBErrorBacktrace = true;' >> LocalSettings.php
+
+if [ "$TYPE" == "debug" ]
+then
+ echo '$wgDebugLogFile = "/tmp/mediawiki-debug.log";' >> LocalSettings.php
+fi
+
+echo "putenv( 'MW_INSTALL_PATH=$(pwd)' );" >> LocalSettings.php
+
+php maintenance/update.php --skip-external-dependencies --quick
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/upload-coverage-report.sh b/www/wiki/extensions/SemanticMediaWiki/tests/travis/upload-coverage-report.sh
new file mode 100644
index 00000000..78f6eae3
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/upload-coverage-report.sh
@@ -0,0 +1,14 @@
+#! /bin/bash
+set -ex
+
+BASE_PATH=$(pwd)
+
+if [ "$TYPE" == "coverage" ]
+then
+ # Use for coveralls.io but currently no working
+ # composer require satooshi/php-coveralls:dev-master
+ # php vendor/bin/coveralls -v
+
+ wget https://scrutinizer-ci.com/ocular.phar
+ php ocular.phar code-coverage:upload --format=php-clover $BASE_PATH/tests/coverage.clover
+fi \ No newline at end of file
diff --git a/www/wiki/extensions/SemanticMediaWiki/tests/travis/virtuoso-sparql-permission.sql b/www/wiki/extensions/SemanticMediaWiki/tests/travis/virtuoso-sparql-permission.sql
new file mode 100644
index 00000000..f0048339
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/tests/travis/virtuoso-sparql-permission.sql
@@ -0,0 +1,6 @@
+GRANT EXECUTE ON DB.DBA.SPARQL_INSERT_DICT_CONTENT TO "SPARQL";
+GRANT EXECUTE ON DB.DBA.SPARQL_DELETE_DICT_CONTENT TO "SPARQL";
+GRANT EXECUTE ON SPARQL_DELETE_DICT_CONTENT to "SPARQL";
+GRANT EXECUTE ON SPARQL_DELETE_DICT_CONTENT to SPARQL_UPDATE;
+GRANT SPARQL_UPDATE to "SPARQL";
+GRANT SPARQL_SPONGE to "SPARQL"; \ No newline at end of file