Completed
Push — master ( e5d845...dc3c24 )
by mw
02:54
created

assertParserOutputForCase()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 17
nc 5
nop 1
dl 0
loc 29
rs 8.439
c 1
b 0
f 0
1
<?php
2
3
namespace SMW\Scribunto\Integration\JSONScript;
4
5
use SMW\Scribunto\HookRegistry;
6
use SMW\Tests\JsonTestCaseScriptRunner;
7
use SMW\Tests\JsonTestCaseFileHandler;
8
use SMW\DIWikiPage;
9
10
/**
11
 * @see https://github.com/SemanticMediaWiki/SemanticMediaWiki/tree/master/tests#write-integration-tests-using-json-script
12
 *
13
 * `JsonTestCaseScriptRunner` provisioned by SMW is a base class allowing to use a JSON
14
 * format to create test definitions with the objective to compose "real" content
15
 * and test integration with MediaWiki, Semantic MediaWiki, and Scribunto.
16
 *
17
 * The focus is on describing test definitions with its content and specify assertions
18
 * to control the expected base line.
19
 *
20
 * `JsonTestCaseScriptRunner` will handle the tearDown process and ensures that no test
21
 * data are leaked into a production system but requires an active DB connection.
22
 *
23
 * @group semantic-scribunto
24
 * @group medium
25
 *
26
 * @license GNU GPL v2+
27
 * @since 1.0
28
 *
29
 * @author mwjames
30
 */
31
class SemanticScribuntoJsonTestCaseScriptRunnerTest extends JsonTestCaseScriptRunner {
32
33
	private $semanticDataValidator;
34
	private $stringValidator;
35
	private $hookRegistry;
36
37
	protected function setUp() {
38
		parent::setUp();
39
40
		$validatorFactory = $this->testEnvironment->getUtilityFactory()->newValidatorFactory();
41
42
		$this->semanticDataValidator = $validatorFactory->newSemanticDataValidator();
43
		$this->stringValidator = $validatorFactory->newStringValidator();
44
45
		$this->hookRegistry = new HookRegistry();
46
47
		$this->hookRegistry->clear();
48
		$this->hookRegistry->register();
49
	}
50
51
	/**
52
	 * @see JsonTestCaseScriptRunner::getRequiredJsonTestCaseMinVersion
53
	 */
54
	protected function getRequiredJsonTestCaseMinVersion() {
55
		return '1';
56
	}
57
58
	/**
59
	 * @see JsonTestCaseScriptRunner::getTestCaseLocation
60
	 */
61
	protected function getTestCaseLocation() {
62
		return __DIR__ . '/TestCases';
63
	}
64
65
	/**
66
	 * Returns a list of files, an empty list is a sign to run all registered
67
	 * tests.
68
	 *
69
	 * @see JsonTestCaseScriptRunner::getListOfAllowedTestCaseFiles
70
	 */
71
	protected function getAllowedTestCaseFiles() {
72
		return array();
73
	}
74
75
	/**
76
	 * @see JsonTestCaseScriptRunner::runTestCaseFile
77
	 *
78
	 * @param JsonTestCaseFileHandler $jsonTestCaseFileHandler
79
	 */
80
	protected function runTestCaseFile( JsonTestCaseFileHandler $jsonTestCaseFileHandler ) {
81
82
		$this->checkEnvironmentToSkipCurrentTest( $jsonTestCaseFileHandler );
83
84
		// Defines settings that can be altered during a test run with each test
85
		// having the possibility to change those value, settings will be reset to
86
		// original value after the test has finished.
87
		$permittedSettings = array(
88
			'smwgNamespacesWithSemanticLinks',
89
			'smwgPageSpecialProperties',
90
			'wgLanguageCode',
91
			'wgContLang',
92
			'wgLang'
93
		);
94
95
		foreach ( $permittedSettings as $key ) {
96
			$this->changeGlobalSettingTo(
97
				$key,
98
				$jsonTestCaseFileHandler->getSettingsFor( $key )
99
			);
100
		}
101
102
		// Pages defined in the JSON setup: { ... } are processed and created
103
		// before the actual assertion
104
		$this->createPagesFor(
0 ignored issues
show
Deprecated Code introduced by
The method SMW\Tests\JsonTestCaseSc...unner::createPagesFor() has been deprecated with message: 2.5

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
105
			$jsonTestCaseFileHandler->getPageCreationSetupList(),
106
			NS_MAIN
107
		);
108
109
		foreach ( $jsonTestCaseFileHandler->findTestCasesByType( 'parser' ) as $case ) {
110
111
			if ( !isset( $case['subject'] ) ) {
112
				break;
113
			}
114
115
			// Assert function are defined individually by each TestCaseRunner
116
			// to ensure a wide range of scenarios can be supported.
117
			$this->assertSemanticDataForCase( $case, $jsonTestCaseFileHandler->getDebugMode() );
118
			$this->assertParserOutputForCase( $case );
119
		}
120
	}
121
122
	/**
123
	 * Assert the SemanticData object available after a entity/page has been
124
	 * stored.
125
	 *
126
	 * ```
127
	 * "assert-store": {
128
	 * 	"semantic-data": {
129
	 * 		"strictPropertyValueMatch": false,
130
	 * 		"propertyCount": 4,
131
	 * 		"propertyKeys": [
132
	 * 			"Testproperty1",
133
	 * 			"Testproperty2",
134
	 * 			"_SKEY",
135
	 * 			"_MDAT"
136
	 * 		],
137
	 * 		"propertyValues": [
138
	 * 			"200"
139
	 * 		]
140
	 * 	}
141
	 * }
142
	 * ```
143
	 */
144
	private function assertSemanticDataForCase( $case, $debugMode ) {
145
146
		// Allows for data to be re-read from the DB instead of being fetched
147
		// from the store-id-cache
148
		if ( isset( $case['store']['clear-cache'] ) && $case['store']['clear-cache'] ) {
149
			$this->store->clear();
150
		}
151
152
		if ( !isset( $case['assert-store'] ) || !isset( $case['assert-store']['semantic-data'] ) ) {
153
			return;
154
		}
155
156
		$subject = DIWikiPage::newFromText(
157
			$case['subject'],
158
			isset( $case['namespace'] ) ? constant( $case['namespace'] ) : NS_MAIN
159
		);
160
161
		$semanticData = $this->store->getSemanticData( $subject );
162
163
		if ( $debugMode ) {
164
			print_r( $semanticData );
165
		}
166
167
		if ( isset( $case['errors'] ) && $case['errors'] !== array() ) {
168
			$this->assertNotEmpty(
169
				$semanticData->getErrors()
170
			);
171
		}
172
173
		$this->semanticDataValidator->assertThatPropertiesAreSet(
174
			$case['assert-store']['semantic-data'],
175
			$semanticData,
176
			$case['about']
177
		);
178
179
		$this->assertInProperties(
180
			$subject,
181
			$case['assert-store']['semantic-data'],
182
			$case['about']
183
		);
184
	}
185
186
	/**
187
	 * Assert the text content which is available after the parse in the
188
	 * ParserOutput object.
189
	 *
190
	 * ```
191
	 * "assert-output": {
192
	 * 	"to-contain": [
193
	 * 		"Foo"
194
	 * 	],
195
	 * 	"not-contain": [
196
	 * 		"Bar"
197
	 * 	]
198
	 * }
199
	 * ```
200
	 */
201
	private function assertParserOutputForCase( $case ) {
202
203
		if ( !isset( $case['assert-output'] ) ) {
204
			return;
205
		}
206
207
		$subject = DIWikiPage::newFromText(
208
			$case['subject'],
209
			isset( $case['namespace'] ) ? constant( $case['namespace'] ) : NS_MAIN
210
		);
211
212
		$parserOutput = $this->testEnvironment->getUtilityFactory()->newPageReader()->getEditInfo( $subject->getTitle() )->output;
0 ignored issues
show
Bug introduced by
It seems like $subject->getTitle() can be null; however, getEditInfo() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
213
214
		if ( isset( $case['assert-output']['to-contain'] ) ) {
215
			$this->stringValidator->assertThatStringContains(
216
				$case['assert-output']['to-contain'],
217
				$parserOutput->getText(),
218
				$case['about']
219
			);
220
		}
221
222
		if ( isset( $case['assert-output']['not-contain'] ) ) {
223
			$this->stringValidator->assertThatStringNotContains(
224
				$case['assert-output']['not-contain'],
225
				$parserOutput->getText(),
226
				$case['about']
227
			);
228
		}
229
	}
230
231
}
232