1<?php
2
3namespace MediaWiki\ParamValidator\TypeDef;
4
5use ChangeTags;
6use MediaWikiIntegrationTestCase;
7use Wikimedia\Message\DataMessageValue;
8use Wikimedia\ParamValidator\ParamValidator;
9use Wikimedia\ParamValidator\SimpleCallbacks;
10use Wikimedia\ParamValidator\ValidationException;
11
12/**
13 * @covers MediaWiki\ParamValidator\TypeDef\TagsDef
14 */
15class TagsDefTest extends MediaWikiIntegrationTestCase {
16
17	protected static $testClass = TagsDef::class;
18
19	protected function setUp(): void {
20		parent::setUp();
21
22		ChangeTags::defineTag( 'tag1' );
23		ChangeTags::defineTag( 'tag2' );
24
25		$this->tablesUsed[] = 'change_tag_def';
26
27		// Since the type def shouldn't care about the specific user,
28		// remove the right from relevant groups to ensure that it's not
29		// checking.
30		$this->setGroupPermissions( [
31			'*' => [ 'applychangetags' => false ],
32			'user' => [ 'applychangetags' => false ],
33		] );
34	}
35
36	/**
37	 * @dataProvider provideValidate
38	 * @param mixed $value Value for getCallbacks()
39	 * @param mixed|ValidationException $expect Expected result from TypeDef::validate().
40	 *  If a ValidationException, it is expected that a ValidationException
41	 *  with matching failure code and data will be thrown. Otherwise, the return value must be equal.
42	 * @param array $settings Settings array.
43	 * @param array $options Options array
44	 * @param array[] $expectConds Expected conditions reported. Each array is
45	 *  `[ $ex->getFailureCode() ] + $ex->getFailureData()`.
46	 */
47	public function testValidate(
48		$value, $expect, array $settings = [], array $options = [], array $expectConds = []
49	) {
50		$callbacks = new SimpleCallbacks( [ 'test' => $value ] );
51		$typeDef = new TagsDef( $callbacks );
52		$settings = $typeDef->normalizeSettings( $settings );
53
54		if ( $expect instanceof ValidationException ) {
55			try {
56				$v = $typeDef->getValue( 'test', $settings, $options );
57				$typeDef->validate( 'test', $v, $settings, $options );
58				$this->fail( 'Expected exception not thrown' );
59			} catch ( ValidationException $ex ) {
60				$this->assertSame(
61					$expect->getFailureMessage()->getCode(),
62					$ex->getFailureMessage()->getCode()
63				);
64				$this->assertSame(
65					$expect->getFailureMessage()->getData(),
66					$ex->getFailureMessage()->getData()
67				);
68			}
69		} else {
70			$v = $typeDef->getValue( 'test', $settings, $options );
71			$this->assertEquals( $expect, $typeDef->validate( 'test', $v, $settings, $options ) );
72		}
73
74		$conditions = [];
75		foreach ( $callbacks->getRecordedConditions() as $c ) {
76			$conditions[] = [ 'code' => $c['message']->getCode(), 'data' => $c['message']->getData() ];
77		}
78		$this->assertSame( $expectConds, $conditions );
79	}
80
81	public function provideValidate() {
82		$settings = [
83			ParamValidator::PARAM_TYPE => 'tags',
84			ParamValidator::PARAM_ISMULTI => true,
85		];
86		$valuesList = [ 'values-list' => [ 'tag1', 'doesnotexist', 'doesnotexist2' ] ];
87
88		return [
89			'Basic' => [ 'tag1', [ 'tag1' ] ],
90			'Bad tag' => [
91				'doesnotexist',
92				new ValidationException(
93					DataMessageValue::new( 'paramvalidator-badtags', [], 'badtags', [
94						'disallowedtags' => [ 'doesnotexist' ],
95					] ),
96					'test', 'doesnotexist', []
97				),
98			],
99			'Multi' => [ 'tag1', 'tag1', $settings, [ 'values-list' => [ 'tag1', 'tag2' ] ] ],
100			'Multi with bad tag (but not the tag)' => [
101				'tag1', 'tag1', $settings, $valuesList
102			],
103			'Multi with bad tag' => [
104				'doesnotexist',
105				new ValidationException(
106					DataMessageValue::new( 'paramvalidator-badtags', [], 'badtags', [
107						'disallowedtags' => [ 'doesnotexist', 'doesnotexist2' ],
108					] ),
109					'test', 'doesnotexist', $settings
110				),
111				$settings, $valuesList
112			],
113		];
114	}
115
116	public function testGetEnumValues() {
117		$typeDef = new TagsDef( new SimpleCallbacks( [] ) );
118		$this->assertSame(
119			ChangeTags::listExplicitlyDefinedTags(),
120			$typeDef->getEnumValues( 'test', [], [] )
121		);
122	}
123
124}
125