Jump to content

User:DannyS712 test/Global watchlist tests.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <nowiki>
/* jshint maxerr: 999 */
/* globals window, GlobalWatchlist, $, mw, OO */
$(function (){
var GlobalWatchlistTests = {};
window.GlobalWatchlistTests = GlobalWatchlistTests;

GlobalWatchlistTests.config = {
	testVersion: '2.3.1', // Last time tests were updated
	scriptVersion: '8.2.2', // Corresponding script version
};
GlobalWatchlistTests.init = async function() {
	console.log( 'Started' );
	mw.util.addCSS(
		'table, th, td { border: 1px solid black; }' +
		'th, td { padding: 5px; }' +
		'.GlobalWatchlistTestsPass { background-color: #00FF00; }' +
		'.GlobalWatchlistTestsFail { background-color: #FF4444; }' +
		'.GlobalWatchlistTestsCheck { background-color: #03fcd7; }' +
		'.GlobalWatchlistTestsWarn { background-color: #ff8400; }'
	);

	$('#mw-content-text').empty().append(
		$( '<table id="GlobalWatchlistTest">' ).append(
			$( '<tr>' ).append( 
				$( '<th>Test</th>' ),
				$( '<th>Expected</th>' ),
				$( '<th>Actual</th>' ),
				$( '<th>Verdict</th>' )
			)
		)
	);
	
	// Every object in GlobalWatchlistTests except the helper methods listed below is a test, which must have at least
	//      * A `desc` string to add as the heading
	//      * A `run` async method, that returns the results of the test
	var tests = Object.keys(GlobalWatchlistTests).filter(e => ['config', 'init', 'testEquality', 'addTestGroupHeading', 'addTestResult', 'makeString', 'addContainerRow'].indexOf(e) === -1);
	var test, testName;
	for ( var iii = 0; iii < tests.length; iii++ ) {
		testName = tests[iii];
		test = GlobalWatchlistTests[ testName ];
		GlobalWatchlistTests.addTestGroupHeading( testName, test.desc );
		var results = await test.run();
		var sum = 0;
		results.forEach((t) => {
			sum = sum + GlobalWatchlistTests.addTestResult( testName, ...t );
		});
		var groupResult = sum === results.length ? 'Pass' : ( sum === 0 ? 'Fail' : 'Warn' );
		$(`#GlobalWatchlistTest-${testName}`).addClass( `GlobalWatchlistTests${groupResult}` );
	}
	$('tr.GlobalWatchlistTestsPass > th.GlobalWatchlistTest-showhide').click();
};
GlobalWatchlistTests.testEquality = function ( a, b ) {
	return Object.is( GlobalWatchlistTests.makeString( a ), GlobalWatchlistTests.makeString( b ) );
};
GlobalWatchlistTests.makeString = function ( o ) {
	var s = o.toString();
	if ( Array.isArray( o ) ) {
		s = o.join(', ');
	} else if ( s === '[object Object]' ) {
		s = Object.entries( o ).toString();
	}
	return s;
};
GlobalWatchlistTests.addTestGroupHeading = function ( name, desc ) {
	$( '#GlobalWatchlistTest' ).append(
		$( `<tr id="GlobalWatchlistTest-${name}">` ).append(
			$( `<th colspan="3" scope="colgroup">${desc}</th>` ),
			$( `<th id="GlobalWatchlistTest-${name}-showhide" class="GlobalWatchlistTest-showhide">Show/hide</th>` )
		)
	);
	$( `#GlobalWatchlistTest-${name}-showhide` ).click( function () {
		$( `.GlobalWatchlistTest-${name}-result` ).toggle();
	});
};
GlobalWatchlistTests.addTestResult = function ( name, desc, expected, actual, warn = false ) {
	if ( expected === 'content' ) {
		GlobalWatchlistTests.addContainerRow( desc, actual, name );
		return 0.5;
	} else {
		var verdict, passTest, result;
		if ( actual !== 'check' ) {
			passTest = GlobalWatchlistTests.testEquality( expected, actual );
			verdict = passTest ? 'Pass' : ( warn ? 'Warn' : 'Fail' );
			result = passTest ? 1 : ( warn ? 0.5 : 0 );
		} else {
			passTest = false;
			verdict = 'Check';
			actual = 'Please check manually';
			result = 0.5;
		}
		$( '#GlobalWatchlistTest' ).append(
			$( `<tr class="GlobalWatchlistTest-${name}-result">` ).append( 
				$( `<td>${ desc }</td>` ),
				$( `<td>${ GlobalWatchlistTests.makeString( expected ) }</td>` ),
				$( `<td>${ GlobalWatchlistTests.makeString( actual ) }</td>` ),
				$( '<td class="GlobalWatchlistTests' + verdict + '">' + verdict + '</td>' )
			)
		);
		console.log( name, expected, actual, verdict );
		return result;
	}
};
GlobalWatchlistTests.addContainerRow = function ( desc, content, name ) {
	$( '#GlobalWatchlistTest' ).append(
		$( `<tr class="GlobalWatchlistTest-${name}-result">` ).append( 
			$( `<td>${ desc }</td>` ),
			$( `<td colspan="2">` ).append( content ),
			$( '<td class="GlobalWatchlistTestsCheck">Check</td>' )
		)
	);
};
GlobalWatchlistTests.sanityCheck = {
	desc: 'Verify that test passing and failing works',
	run: async function () {
		return [
			[ 'Should pass', true, true ],
			[ 'Should fail', true, false ]
		];
	}
};
GlobalWatchlistTests.testInit = {
	desc: 'Test startup processes (`init`, `setMode`, and messages)',
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			resolve([
				[ 'Activated in test mode', 4, GlobalWatchlist.cfg.mode ],
				[ 'Testing without actions', true, GlobalWatchlist.cfg.testNoActions ],
				[ 'Retrieved `rcfilters-filter-minor-label` properly', "Minor edits", mw.msg( 'gw-msg-filter-minor') ],
				[ 'Set `globalWatchlistBackLink` properly', "Back to Global watchlist", mw.msg( 'gw-msg-globalWatchlistBackLink') ],
			]);
		});
	}
};
GlobalWatchlistTests.settingsValidate = {
	desc: 'Test `settings.validate`',
	run: async function () {
		const GlobalWatchlist = window.GlobalWatchlist;
		var tests = GlobalWatchlistTests.settingsValidate.data;
		var results = [];
		for ( var iii = 0; iii < tests.length; iii++ ){
			results.push( [ tests[iii][0], tests[iii][2], await GlobalWatchlist.settings.validate( tests[iii][1] ) ] );
		}
		return results;
	},
	data: [
		[ 'Need at least 1 site',
			{
				sites: [],
				botFilter: 0,
				anonFilter: 0,
				minorFilter: 0,
				showEdits: true,
				showNewPages: true,
				showLogEntries: true,
				groupPage: true
			},
			[ 'No sites selected' ]
		],
		[ 'Invalid site',
			{
				sites: [ 'foo.bar' ],
				botFilter: 0,
				anonFilter: 0,
				minorFilter: 0,
				showEdits: true,
				showNewPages: true,
				showLogEntries: true,
				groupPage: true
			},
			[ 'Invalid site(s): foo.bar' ]
		],
		[ 'Some sites invalid',
			{
				sites: [ 'foo.bar', 'en.wikipedia' ],
				botFilter: 0,
				anonFilter: 0,
				minorFilter: 0,
				showEdits: true,
				showNewPages: true,
				showLogEntries: true,
				groupPage: true
			},
			[ 'Invalid site(s): foo.bar' ]
		],
		[ 'All sites invalid',
			{
				sites: [ 'foo.bar', 'biz.baz' ],
				botFilter: 0,
				anonFilter: 0,
				minorFilter: 0,
				showEdits: true,
				showNewPages: true,
				showLogEntries: true,
				groupPage: true
			},
			[ 'Invalid site(s): foo.bar, biz.baz' ]
		],
		[ 'Need to show something',
			{
				sites: [ 'en.wikipedia' ],
				botFilter: 0,
				anonFilter: 0,
				minorFilter: 0,
				showEdits: false,
				showNewPages: false,
				showLogEntries: false,
				groupPage: true
			},
			[ 'No change types selected' ]
		],
		[ 'No anon bots',
			{
				sites: [ 'en.wikipedia' ],
				botFilter: 1,
				anonFilter: 1,
				minorFilter: 0,
				showEdits: true,
				showNewPages: true,
				showLogEntries: true,
				groupPage: true
			},
			[ 'Anonymous users cannot make bot edits' ]
		],
		[ 'No anon minor edits',
			{
				sites: [ 'en.wikipedia' ],
				botFilter: 0,
				anonFilter: 1,
				minorFilter: 1,
				showEdits: true,
				showNewPages: true,
				showLogEntries: true,
				groupPage: true
			},
			[ 'Anonymous users cannot make minor edits' ]
		],
		[ 'No problems',
			{
				sites: [ 'en.wikipedia' ],
				botFilter: 0,
				anonFilter: 0,
				minorFilter: 0,
				showEdits: true,
				showNewPages: true,
				showLogEntries: true,
				groupPage: true
			},
			[]
		],
	]
};
GlobalWatchlistTests.helpFlag = {
	desc: 'Test `help.flag`',
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			var tests = GlobalWatchlistTests.helpFlag.data;
			var results = [];
			for ( var iii = 0; iii < tests.length; iii++ ){
				results.push( [ tests[iii][0], tests[iii][3], GlobalWatchlist.help.flag( tests[iii][1], tests[iii][2] ) ] );
			}
			resolve(results);
		});
	},
	data: [
		[ 'Inclusive', 1, 'filter', '|filter' ],
		[ 'Exclusive', 2, 'filter', '|!filter' ],
		[ 'Other', 0, 'filter', '' ]
	]
};
GlobalWatchlistTests.helpSetUp = {
	desc: 'Test `help.setUp`',
	msg: {
		'gw-msg-title-tests': 'Global watchlist tests (T)',
		'gw-msg-heading-tests': 'Global watchlist tests (H)'
	},
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			var msg = GlobalWatchlistTests.helpSetUp.msg;
			mw.messages.set( msg );
			GlobalWatchlist.help.setUp( 4, 'tests' );
			resolve([
				[ 'Page title', msg[ 'gw-msg-title-tests' ], 'check' ],
				[ 'Page heading', msg[ 'gw-msg-heading-tests' ], 'check' ]
			]);
		});
	}
};
GlobalWatchlistTests.checkDocsExist = {
	desc: 'Verify that QQQ documentation and unit numbers exist for all messages',
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			var en = GlobalWatchlist.i18n.en,
				enKeys = Object.keys( en ),
				enStringed = JSON.stringify( enKeys, null, ' ' ),
				qqq = GlobalWatchlist.i18n.qqq,
				qqqKeys = Object.keys( qqq ),
				qqqStringed = JSON.stringify( qqqKeys, null, ' ' ),
				units = GlobalWatchlist.i18n.units,
				unitsKeys = Object.keys( units ),
				unitsStringed = JSON.stringify( unitsKeys, null, ' ' );
	
			var unitsV = Object.values( units ),
				unitsS = [ ...new Set( unitsV ) ];
	
			resolve([
				[ 'Names of keys (qqq)', enStringed, qqqStringed ],
				[ 'Names of keys (units)', enStringed, unitsStringed, true ],
				[ 'No duplicate units (set = array)', unitsV, unitsS ],
			]);
		});
	}
};
GlobalWatchlistTests.checkNoExtraMsg = {
	desc: 'Verify that only messages with English definitions are translated',
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			var langs = Object.keys(GlobalWatchlist.i18n).filter(e => ['en', 'mwMsgs', 'qqq', 'units'].indexOf(e) === -1);
			var enkeys = Object.keys(GlobalWatchlist.i18n.en);
			var lang;
			var results = [];
			for ( var iii = 0; iii < langs.length; iii++ ) {
				lang = langs[iii];
				results.push( [ lang + ' translations', [], Object.keys(GlobalWatchlist.i18n[ langs[iii] ]).filter(e => enkeys.indexOf(e) === -1) ] );
			}
			resolve(results);
		});
	}
};
GlobalWatchlistTests.labelE = {
	desc: 'Test `OOUI.labelE`',
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			mw.messages.set( 'gw-msg-exampleLabel', 'Example label text' );
			resolve([ [
				'Label creation',
				'&lt;label class="oo-ui-widget oo-ui-widget-enabled oo-ui-labelElement oo-ui-labelElement-label oo-ui-labelWidget" aria-disabled="false"&gt;Example label text&lt;/label&gt;',
				GlobalWatchlist.OOUI.labelE( 'exampleLabel' )[0].outerHTML.replace( /</g, '&lt;' ).replace( />/g, '&gt;' )
			] ]);
		});
	}
}
GlobalWatchlistTests.basicSiteObject = {
	desc: 'Test `GlobalWatchlist.Site` object (basic)',
	run: async function () {
		const GlobalWatchlist = window.GlobalWatchlist;
		var tests = GlobalWatchlistTests.basicSiteObject.data;
		var site, test, siteName;
		results = [];
		for ( var iii = 0; iii < tests.length; iii++ ){
			test = tests[iii];
			siteName = test[ 0 ];
			site = new GlobalWatchlist.Site( siteName )
			results.push( [ `Site.site - ${siteName}`, siteName, site.site ] );
			results.push( [ `Site.siteID - ${siteName}`, test[ 1 ], site.siteID ] );
			results.push( [ `Site.divID - ${siteName}`, test[ 2 ], site.divID ] );
			results.push( [ `getAssociatedPageTitle - ${siteName}`, test[ 3 ], decodeURIComponent( ( await site.getAssociatedPageTitle( test[ 4 ] ) ).replace(/%27/g, '\'').replace(/%22/g, 'DOUBLEQUOTE') ) ] );
		}
		return results;
	},
	data: [
		[ 'en.wikipedia', 'en_wikipedia', 'globalWatch-feed-site-en_wikipedia', 'User talk:DannyS712', 'User:DannyS712' ],
		[ 'es.wikinews', 'es_wikinews', 'globalWatch-feed-site-es_wikinews', 'Usuario discusión:Foo', 'Usuario:Foo' ],
		[ 'meta.wikimedia', 'meta_wikimedia', 'globalWatch-feed-site-meta_wikimedia', 'Meta:Requests for help from a sysop or bureaucrat', 'Meta talk:Requests for help from a sysop or bureaucrat' ],
		[ 'ko.wikiversity', 'ko_wikiversity', 'globalWatch-feed-site-ko_wikiversity', '사용자:Bar', '사용자토론:Bar' ],
	],
}
GlobalWatchlistTests.advancedSiteObject = {
	desc: 'Test `GlobalWatchlist.Site` object (advanced)',
	mockApi: function ( site ) {
		this.realApi = new mw.ForeignApi(`//${site}.org/w/api.php`);
		this.get = function ( options ) {
			return new Promise((resolve) => {
				console.log( 'Tests API, get:', options );
				if ( options.action === 'parse' ) {
					console.log( 'Parsing for associated title, use real api' );
					resolve(this.realApi.get( options ));
				} else if ( options.action === 'query' ) {
					if ( options.list === 'tags' ) {
						console.log( 'Querying for tags, will need to return fake' );
						resolve(GlobalWatchlistTests.advancedSiteObject.fakeData.tags);
					} else if ( options.list === 'watchlist' ) {
						console.log( 'Querying for watchlist, will need to return fake' );
						resolve(GlobalWatchlistTests.advancedSiteObject.fakeData.watchlist);
					}
				} else if ( options.action === 'wbgetentities' ) {
					console.log( 'Querying for wikidata entities, will need to return fake' );
					resolve(this.realApi.get( options ));
				}
			});
		};
	},
	fakeData: {
		watchlist: {
			"batchcomplete": true,
			"limits": {
				"watchlist": 500
			},
			"query": {
				"watchlist": [
					{
						"type": "edit",
						"ns": 0,
						"title": "Foo",
						"pageid": 1,
						"revid": 1002,
						"old_revid": 1001,
						"user": "User 1",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "Summary 1",
						"tags": [ 'OAuth CID: 1234' ]
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Bar",
						"pageid": 2,
						"revid": 2002,
						"old_revid": 2001,
						"user": "User 2",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "<span dir=\"auto\"><span class=\"autocomment\"><a href=\"/wiki/Section heading\" title=\"Section heading\">→‎Section heading</a></span></span>",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Baz",
						"pageid": 3,
						"revid": 3003,
						"old_revid": 3001,
						"user": "Bot User",
						"bot": true,
						"new": false,
						"minor": false,
						"parsedcomment": "Bot comment",
						"tags": []
					},
					{
						"type": "new",
						"ns": 0,
						"title": "Qux",
						"pageid": 4,
						"revid": 4004,
						"user": "New page creator",
						"bot": false,
						"new": true,
						"minor": false,
						"parsedcomment": "Look what I made!",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Lorem ipsum",
						"pageid": 5,
						"revid": 5005,
						"old_revid": 5001,
						"user": "Copy editor",
						"bot": false,
						"new": false,
						"minor": true,
						"parsedcomment": "Fixed some typos",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Page",
						"pageid": 6,
						"revid": 6006,
						"old_revid": 6001,
						"user": "127.0.01",
						"anon": true,
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "The truth",
						"tags": [ 'blanking' ]
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Page to be edited with no summary",
						"pageid": 7,
						"revid": 7007,
						"old_revid": 7001,
						"user": "Demo user",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "",
						"tags": []
					},
					{
						"type": "log",
						"ns": 0,
						"title": "Page that was deleted",
						"pageid": 8,
						"revid": 0,
						"old_revid": 0,
						"user": "Admin",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "I did the deletion",
						"logid": 8008,
						"logtype": "delete",
						"logaction": "delete",
						"logparams": {},
						"tags": []
					},
					{
						"type": "log",
						"ns": 2,
						"title": "User:Vandal",
						"pageid": 0,
						"revid": 0,
						"old_revid": 0,
						"user": "Admin",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "You have been blocked for <a href=\"/wiki/WP:VD\" class=\"mw-redirect\" title=\"WP:VD\">vandalism</a>",
						"logid": 9009,
						"logtype": "block",
						"logaction": "block",
						"logparams": {
							"duration": "1 month",
							"flags": [ "nocreate", "noemail" ],
							"sitewide": true,
							"expiry": "2020-02-12T12:15:30Z"
						},
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Page to be edited with RTL users",
						"pageid": 8,
						"revid": 8008,
						"old_revid": 8001,
						"user": "ערן",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Page to be edited with RTL users",
						"pageid": 8,
						"revid": 8009,
						"old_revid": 8008,
						"user": "ערן",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Page to be edited with RTL users",
						"pageid": 8,
						"revid": 8010,
						"old_revid": 8009,
						"user": "DannyS712",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "Page to be edited with hidden user",
						"pageid": 9,
						"revid": 9009,
						"old_revid": 9001,
						"userhidden": true,
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "",
						"tags": []
					},
					{
						"type": "new",
						"ns": 0,
						"title": "New page with lots of edits",
						"pageid": 10,
						"revid": 10001,
						"user": "New page creator",
						"bot": false,
						"new": true,
						"minor": false,
						"parsedcomment": "Look what I made!",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "New pages with lots of edits",
						"pageid": 10,
						"revid": 10002,
						"old_revid": 10001,
						"user": "DannyS712",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "",
						"tags": []
					},
					{
						"type": "edit",
						"ns": 0,
						"title": "New pages with lots of edits",
						"pageid": 10,
						"revid": 10003,
						"old_revid": 10002,
						"user": "DannyS712",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "",
						"tags": []
					}
				]
			}
		},
		tags: {
			"batchcomplete": true,
			"limits": {
				"tags": 500
			},
			"query": {
				"tags": [
					{
						"name": "OAuth CID: 1234",
						"displayname": "<a href=\"/wiki/Special:OAuthListConsumers/view/OAuthTag\" title=\"Special:OAuthListConsumers/view/OAuthTag\">OAuthTag</a>"
					},
					{
						"name": "abusefilter-condition-limit",
						"displayname": "condition limit reached"
					},
					{
						"name": "blanking",
						"displayname": "blanking"
					},
				]
			}
		}
	},
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			GlobalWatchlist.help.api = function ( site ) {
				return new GlobalWatchlistTests.advancedSiteObject.mockApi( site );
			}
			const enwiki = new GlobalWatchlist.Site( 'en.wikipedia' );
			enwiki.getWatchlist().then( function () {
				var expectedTags = GlobalWatchlistTests.advancedSiteObject.fakeData.tags.query.tags,
					expectedTagsObject = {};
				expectedTags.forEach((t) => { expectedTagsObject[t.name] = t.displayname || false ? t.displayname.replace(/<a href="\/wiki\//g, `<a href="/wiki/`) : t.name; })
				resolve([
					[ `Site.tags`, expectedTagsObject, enwiki.tags ],
					[ `Site.isEmpty`, false, enwiki.isEmpty ],
					[ `Edits - new`, '"New page creator" created Qux', 'check' ],
					[ `Edits - bot`, '"Bot User" edited Baz with a bot edit', 'check' ],
					[ `Edits - minor`, '"Copy editor" edited Lorem ipsum with a minor edit', 'check' ],
					[ `Edits - tag`, '"User 1"\'s edit is tagged as "OAuthTag"', 'check' ],
					[ `Edits - tag`, '"127.0.0.1"\'s edit is tagged as "blanking"', 'check' ],
					[ `Edits - link (user)`, '"User 2"\'s name is linked to their user page', 'check' ],
					[ `Edits - link (anon)`, '"127.0.0.1"\'s name is linked to their contributions', 'check' ],
					[ `Edits - empty summary`, 'There is no extra : when no summary accompanies an edit', 'check' ],
					[ `Log - deletion`, '"Admin" is shown deleting a page', 'check' ],
					[ `Log - block`, '"Admin" is shown blocking "Vandal"', 'check' ],
					[ 'Edits - RTL', 'RTL users with multiple edits work properly', 'check' ],
					[ 'Unwatch - strikethrough', 'Unwatching a page results in strikethrough through links', 'check' ],
					[ 'Hidden user', 'Edits where the user is hidden are shown as a hidden user, rather than undefined', 'check' ],
					[ 'Links in separate tabs', 'Links to pages, user pages, contributions, history, etc. open in a separate tab', 'check' ],
					[ 'Collapsable', 'A "hide" button allows collapsing the output of the site', 'check' ],
					[ `Enwiki feed object`, 'content', enwiki.$feedDiv ]
				]);
			} );
		});
	}
}
GlobalWatchlistTests.wikidataSite = {
	desc: 'Test `GlobalWatchlist.Site` object for wikidata',
	mockApi: function ( site ) {
		this.realApi = new mw.ForeignApi(`//${site}.org/w/api.php`);
		this.get = function ( options ) {
			return new Promise((resolve) => {
				console.log( 'Tests API, get:', options );
				if ( options.action === 'parse' ) {
					console.log( 'Parsing for associated title, use real api' );
					resolve(this.realApi.get( options ));
				} else if ( options.action === 'query' ) {
					if ( options.list === 'tags' ) {
						console.log( 'Querying for tags, will need to return fake' );
						resolve(GlobalWatchlistTests.wikidataSite.fakeData.tags);
					} else if ( options.list === 'watchlist' ) {
						console.log( 'Querying for watchlist, will need to return fake' );
						resolve(GlobalWatchlistTests.wikidataSite.fakeData.watchlist);
					}
				} else if ( options.action === 'wbgetentities' ) {
					console.log( 'Querying for wikidata entities, will need to return fake' );
					resolve(this.realApi.get( options ));
				}
			});
		};
	},
	fakeData: {
		watchlist: {
			"batchcomplete": true,
			"limits": {
				"watchlist": 500
			},
			"query": {
				"watchlist": [
					{
						"type": "edit",
						"ns": 0,
						"title": "Q5",
						"pageid": 1,
						"revid": 1002,
						"old_revid": 1001,
						"user": "User 1",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "Item summary"
					},
					{
						"type": "edit",
						"ns": 120,
						"title": "Property:P31",
						"pageid": 2,
						"revid": 2002,
						"old_revid": 2001,
						"user": "User 2",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "Property summary",
						"tags": [ 'property' ]
					},
					{
						"type": "edit",
						"ns": 146,
						"title": "Lexeme:L2",
						"pageid": 3,
						"revid": 3003,
						"old_revid": 3001,
						"user": "User 3",
						"bot": false,
						"new": false,
						"minor": false,
						"parsedcomment": "Lexeme summary",
						"tags": []
					}
				]
			}
		},
		tags: {
			"batchcomplete": true,
			"limits": {
				"tags": 500
			},
			"query": {
				"tags": [
					{
						"name": "property",
						"displayname": "Property edit"
					},
				]
			}
		}
	},
	run: function () {
		return new Promise((resolve) => {
			const GlobalWatchlist = window.GlobalWatchlist;
			GlobalWatchlist.help.api = function ( site ) {
				return new GlobalWatchlistTests.wikidataSite.mockApi( site );
			}
			const wd = new GlobalWatchlist.Site( 'www.wikidata' );
			wd.getWatchlist().then( function () {
				var expectedTags = GlobalWatchlistTests.wikidataSite.fakeData.tags.query.tags,
					expectedTagsObject = {};
				expectedTags.forEach((t) => { expectedTagsObject[t.name] = t.displayname || false ? t.displayname.replace(/<a href="\/wiki\//g, `<a href="/wiki/`) : t.name; })
				resolve([
					[ `Labels - Q`, 'Q5 is "human"', 'check' ],
					[ `Labels - P`, 'P31 is "instance of"', 'check' ],
					[ `Labels - L`, 'L2 is "first"', 'check' ],
					[ `Wikidata feed object`, 'content', wd.$feedDiv ]
				]);
			} );
		});
	}
}
} );
mw.loader.using( [ 'mediawiki.util', 'mediawiki.api', 'mediawiki.ForeignApi', 'oojs-ui-core', 'oojs-ui-windows' ], function () {
	$(document).ready( function () {
		if ( mw.config.get('wgNamespaceNumber') === -1 ){
			var page = mw.config.get('wgCanonicalSpecialPageName');
			if ( page === 'Blankpage'){
				var page2 = mw.config.get( 'wgTitle' ).split('/');
				if ( page2[1] ) {
					if ( page2[1] === 'GlobalWatchlistTests' ) {
						mw.hook( 'GlobalWatchlistInternal' ).add( window.GlobalWatchlistTests.init );
						mw.loader.getScript( '/w/index.php?title=User:DannyS712 test/Global watchlist.js&action=raw&ctype=text/javascript' ).then( function () {
							window.GlobalWatchlist.init( 4 );
						} );
					}
				}
			}
		}
	} );
} );

// </nowiki>