diff --git a/src/modules/twinkletag.js b/src/modules/twinkletag.js
index 6a146f5dd..fc0fe6980 100644
--- a/src/modules/twinkletag.js
+++ b/src/modules/twinkletag.js
@@ -547,46 +547,6 @@ const translationSubgroups = [
}
] : []);
-// Subgroups for {{merge}}, {{merge-to}} and {{merge-from}}
-const getMergeSubgroups = function(tag) {
- let otherTagName = 'Merge';
- switch (tag) {
- case 'Merge from':
- otherTagName = 'Merge to';
- break;
- case 'Merge to':
- otherTagName = 'Merge from';
- break;
- // no default
- }
- return [
- {
- name: 'mergeTarget',
- type: 'input',
- label: 'Other article(s):',
- tooltip: 'If specifying multiple articles, separate them with pipe characters: Article one|Article two',
- required: true
- },
- {
- type: 'checkbox',
- list: [
- {
- name: 'mergeTagOther',
- label: 'Tag the other article with a {{' + otherTagName + '}} tag',
- checked: true,
- tooltip: 'Only available if a single article name is entered.'
- }
- ]
- }
- ].concat(mw.config.get('wgNamespaceNumber') === 0 ? {
- name: 'mergeReason',
- type: 'textarea',
- label: 'Rationale for merge (will be posted on ' +
- (tag === 'Merge to' ? 'the other article\'s' : 'this article\'s') + ' talk page):',
- tooltip: 'Optional, but strongly recommended. Leave blank if not wanted. Only available if a single article name is entered.'
- } : []);
-};
-
// Tags arranged by category; will be used to generate the alphabetical list,
// but tags should be in alphabetical order within the categories
// excludeMI: true indicate a tag that *does not* work inside {{multiple issues}}
@@ -930,13 +890,7 @@ Twinkle.tag.article.tagList = {
tooltip: 'For complex cases, provide extra instructions for the reviewing administrator.'
}
]
- },
- { tag: 'Merge', description: 'should be merged with another given article', excludeMI: true,
- subgroup: getMergeSubgroups('Merge') },
- { tag: 'Merge from', description: 'another given article should be merged into this one', excludeMI: true,
- subgroup: getMergeSubgroups('Merge from') },
- { tag: 'Merge to', description: 'should be merged into another given article', excludeMI: true,
- subgroup: getMergeSubgroups('Merge to') }
+ }
],
Splitting: [
{ tag: 'Split', description: 'should be split into multiple pages' },
@@ -1402,41 +1356,6 @@ Twinkle.tag.callbacks = {
coiTalkPage.newSection();
}
- // Special functions for merge tags
- // Post a rationale on the talk page (mainspace only)
- if (params.mergeReason) {
- const mergeTalkPage = new Morebits.wiki.Page('Talk:' + params.discussArticle, 'Posting rationale on talk page');
- mergeTalkPage.setNewSectionText(params.mergeReason.trim() + ' ~~~~');
- mergeTalkPage.setNewSectionTitle(params.talkDiscussionTitleLinked);
- mergeTalkPage.setChangeTags(Twinkle.changeTags);
- mergeTalkPage.setWatchlist(Twinkle.getPref('watchMergeDiscussions'));
- mergeTalkPage.setCreateOption('recreate');
- mergeTalkPage.newSection();
- }
- // Tag the target page (if requested)
- if (params.mergeTagOther) {
- let otherTagName = 'Merge';
- if (params.mergeTag === 'Merge from') {
- otherTagName = 'Merge to';
- } else if (params.mergeTag === 'Merge to') {
- otherTagName = 'Merge from';
- }
- const newParams = {
- tags: [otherTagName],
- tagsToRemove: [],
- tagsToRemain: [],
- mergeTarget: Morebits.pageNameNorm,
- discussArticle: params.discussArticle,
- talkDiscussionTitle: params.talkDiscussionTitle,
- talkDiscussionTitleLinked: params.talkDiscussionTitleLinked
- };
- const otherpage = new Morebits.wiki.Page(params.mergeTarget, 'Tagging other page (' +
- params.mergeTarget + ')');
- otherpage.setChangeTags(Twinkle.changeTags);
- otherpage.setCallbackParameters(newParams);
- otherpage.load(Twinkle.tag.callbacks.article);
- }
-
// Special functions for {{not English}} and {{rough translation}}
// Post at WP:PNT (mainspace only)
if (params.translationPostAtPNT) {
@@ -1619,30 +1538,6 @@ Twinkle.tag.callbacks = {
currentTag += '|listed=yes';
}
break;
- case 'Merge':
- case 'Merge to':
- case 'Merge from':
- params.mergeTag = tagName;
- // normalize the merge target for now and later
- params.mergeTarget = Morebits.string.toUpperCaseFirstChar(params.mergeTarget.replace(/_/g, ' '));
-
- currentTag += '|' + params.mergeTarget;
-
- // link to the correct section on the talk page, for article space only
- if (mw.config.get('wgNamespaceNumber') === 0 && (params.mergeReason || params.discussArticle)) {
- if (!params.discussArticle) {
- // discussArticle is the article whose talk page will contain the discussion
- params.discussArticle = tagName === 'Merge to' ? params.mergeTarget : mw.config.get('wgTitle');
- // nonDiscussArticle is the article which won't have the discussion
- params.nonDiscussArticle = tagName === 'Merge to' ? mw.config.get('wgTitle') : params.mergeTarget;
- const direction = '[[' + params.nonDiscussArticle + ']]' + (params.mergeTag === 'Merge' ? ' with ' : ' into ') + '[[' + params.discussArticle + ']]';
- params.talkDiscussionTitleLinked = 'Proposed merge of ' + direction;
- params.talkDiscussionTitle = params.talkDiscussionTitleLinked.replace(/\[\[(.*?)\]\]/g, '$1');
- }
- const titleWithSectionRemoved = params.discussArticle.replace(/^([^#]*)#.*$/, '$1'); // If article name is Test#Section, delete #Section
- currentTag += '|discuss=Talk:' + titleWithSectionRemoved + '#' + params.talkDiscussionTitle;
- }
- break;
default:
break;
}
@@ -1693,15 +1588,11 @@ Twinkle.tag.callbacks = {
tags.push(tag);
}
} else {
- if (tag === 'Merge from' || tag === 'History merge') {
+ if (tag === 'History merge') {
tags.push(tag);
} else {
Morebits.Status.warn('Info', 'Found {{' + tag +
'}} on the article already...excluding');
- // don't do anything else with merge tags
- if (['Merge', 'Merge to'].includes(tag)) {
- params.mergeTarget = params.mergeReason = params.mergeTagOther = null;
- }
}
}
});
@@ -2038,17 +1929,6 @@ Twinkle.tag.callback.evaluate = function twinkletagCallbackEvaluate(e) {
params.tagsToRemove = form.getUnchecked('existingTags'); // not in `input`
params.tagsToRemain = params.existingTags || []; // container not created if none present
- if ((params.tags.includes('Merge')) || (params.tags.includes('Merge from')) ||
- (params.tags.includes('Merge to'))) {
- if (Twinkle.tag.checkIncompatible(['Merge', 'Merge from', 'Merge to'], params.tags, 'If several merges are required, use {{Merge}} and separate the article names with pipes (although in this case Twinkle cannot tag the other articles automatically).')) {
- return;
- }
- if ((params.mergeTagOther || params.mergeReason) && params.mergeTarget.includes('|')) {
- alert('Tagging multiple articles in a merge, and starting a discussion for multiple articles, is not supported at the moment. Please turn off "tag other article", and/or clear out the "reason" box, and try again.');
- return;
- }
- }
-
if (Twinkle.tag.checkIncompatible(['Not English', 'Rough translation'], params.tags)) {
return;
}
diff --git a/src/modules/twinklexfd.js b/src/modules/twinklexfd.js
index ef34367bb..8783a029e 100644
--- a/src/modules/twinklexfd.js
+++ b/src/modules/twinklexfd.js
@@ -317,6 +317,27 @@ Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory
style: 'margin-bottom: 5px; margin-top: -5px;'
});
+ work_area.append({
+ type: 'select',
+ name: 'outcome',
+ label: 'Desired outcome:',
+ event: Twinkle.xfd.callbacks.changeAfdOutcome,
+ list: [
+ { label: 'Delete', value: 'deletion' },
+ { label: 'Merge', value: 'merging' },
+ { label: 'Redirect', value: 'redirecting' },
+ { label: 'Draftify', value: 'draftification' }
+ ]
+ });
+
+ work_area.append({
+ name: 'afdtarget',
+ type: 'input',
+ label: 'Target page:',
+ tooltip: 'Target page for the redirect or merge.',
+ event: Twinkle.xfd.callbacks.changeAfdTarget
+ });
+
work_area.append({
type: 'checkbox',
list: [
@@ -373,6 +394,9 @@ Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);
+ // Now that we've rendered the form, hide the target text box. Unhide it later for certain outcomes, using a callback.
+ $('[name="afdtarget"]').parent().hide();
+
Twinkle.makeFindSourcesDiv('#twinkle-xfd-findsources');
$(work_area).find('[name=delsortCats]')
@@ -750,7 +774,50 @@ Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory
};
Twinkle.xfd.callbacks = {
- // Requires having the tag text (params.tagText) set ahead of time
+ /** If the user hasn't modified the reason much, modify the reason to include the target article. If the user has modified the reason box with a custom reason, do nothing, since we don't want to blank their work. */
+ changeAfdTarget: function() {
+ const $afdTarget = $('[name="afdtarget"]');
+ const $reason = $('[name="reason"]');
+ const $outcome = $('[name="outcome"]');
+ if ($reason.val().endsWith('because ')) {
+ // Target has something typed in
+ if ($afdTarget.val()) {
+ if ($outcome.val() === 'redirecting') {
+ $reason.val(`I propose '''redirecting''' to [[${$afdTarget.val()}]] because `);
+ } else if ($outcome.val() === 'merging') {
+ $reason.val(`I propose '''merging''' to [[${$afdTarget.val()}]] because `);
+ }
+ // Target is blank
+ } else {
+ if ($outcome.val() === 'redirecting') {
+ $reason.val("I propose '''redirecting''' because ");
+ } else if ($outcome.val() === 'merging') {
+ $reason.val("I propose '''merging''' because ");
+ }
+ }
+ }
+ },
+ /** Print a default reason in the reason textarea, depending on which outcome is selected from the outcome dropdown list. */
+ changeAfdOutcome: function() {
+ const $outcome = $('[name="outcome"]');
+ const $reason = $('[name="reason"]');
+ const $afdTarget = $('[name="afdtarget"]');
+ $afdTarget.val('');
+ if ($outcome.val() === 'redirecting') {
+ $reason.val("I propose '''redirecting''' because ");
+ $afdTarget.parent().show();
+ } else if ($outcome.val() === 'merging') {
+ $reason.val("I propose '''merging''' because ");
+ $afdTarget.parent().show();
+ } else if ($outcome.val() === 'draftification') {
+ $reason.val("I propose '''draftifying''' because ");
+ $afdTarget.parent().hide();
+ } else if ($outcome.val() === 'deletion') {
+ $reason.val('');
+ $afdTarget.parent().hide();
+ }
+ },
+ /** Requires having the tag text (params.tagText) set ahead of time */
autoEditRequest: function(pageobj, params) {
const talkName = new mw.Title(pageobj.getPageName()).getTalkPage().toText();
if (talkName === pageobj.getPageName()) {
@@ -900,11 +967,12 @@ Twinkle.xfd.callbacks = {
// Ensure items with User talk or no namespace prefix both end
// up at user talkspace as expected, but retain the
// prefix-less username for addToLog
- notifyTarget = mw.Title.newFromText(notifyTarget, 3);
+ const userTalkNamespace = 3;
+ notifyTarget = mw.Title.newFromText(notifyTarget, userTalkNamespace);
const targetNS = notifyTarget.getNamespaceId();
- const usernameOrTarget = notifyTarget.getRelativeText(3);
+ const usernameOrTarget = notifyTarget.getRelativeText(userTalkNamespace);
notifyTarget = notifyTarget.toText();
- if (targetNS === 3) {
+ if (targetNS === userTalkNamespace) {
// Disallow warning yourself
if (usernameOrTarget === mw.config.get('wgUserName')) {
Morebits.Status.warn('You (' + usernameOrTarget + ') created this page; skipping user notification');
@@ -919,25 +987,7 @@ Twinkle.xfd.callbacks = {
actionName = actionName || 'Notifying initial contributor (' + usernameOrTarget + ')';
}
- let notifytext = '\n{{subst:' + params.venue + ' notice';
- // Venue-specific parameters
- switch (params.venue) {
- case 'afd':
- case 'mfd':
- notifytext += params.numbering !== '' ? '|order= ' + params.numbering : '';
- break;
- case 'tfd':
- if (params.xfdcat === 'tfm') {
- notifytext = '\n{{subst:Tfm notice|2=' + params.tfdtarget;
- }
- break;
- case 'cfd':
- notifytext += '|action=' + params.action + (mw.config.get('wgNamespaceNumber') === 10 ? '|stub=yes' : '');
- break;
- default: // ffd, rfd
- break;
- }
- notifytext += '|1=' + Morebits.pageNameNorm + '}} ~~~~';
+ const notifyText = Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params);
// Link to the venue; object used here rather than repetitive items in switch
const venueNames = {
@@ -952,7 +1002,7 @@ Twinkle.xfd.callbacks = {
Morebits.pageNameNorm + ']] at [[WP:' + venueNames[params.venue] + ']].';
const usertalkpage = new Morebits.wiki.Page(notifyTarget, actionName);
- usertalkpage.setAppendText(notifytext);
+ usertalkpage.setAppendText(notifyText);
usertalkpage.setEditSummary(editSummary);
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
@@ -980,6 +1030,37 @@ Twinkle.xfd.callbacks = {
});
}
},
+ generateUserTalkNoticeWikitext: function(params) {
+ // For grep: Afd notice, Mfd notice, Tfd notice, Cfd notice, Ffd notice, Rfd notice
+ let notifytext = '\n{{subst:' + params.venue + ' notice';
+ const templateNamespace = 10;
+ // Venue-specific parameters
+ switch (params.venue) {
+ case 'afd':
+ notifytext += params.outcome !== 'deletion' ? '|outcome=' + params.outcome : '';
+ notifytext += params.afdtarget ? '|target=' + params.afdtarget : '';
+ // Tell the template to add " (Xnd nomination)" to the XFD title, if needed.
+ // The (HTML space character) is needed to overcome MediaWiki's parameter auto-trim.
+ notifytext += params.numbering !== '' ? '|order= ' + params.numbering : '';
+ break;
+ case 'mfd':
+ // tell the template to add " (Xnd nomination)" to the XFD title, if needed
+ notifytext += params.numbering !== '' ? '|order= ' + params.numbering : '';
+ break;
+ case 'tfd':
+ if (params.xfdcat === 'tfm') {
+ notifytext = '\n{{subst:Tfm notice|2=' + params.tfdtarget;
+ }
+ break;
+ case 'cfd':
+ notifytext += '|action=' + params.action + (mw.config.get('wgNamespaceNumber') === templateNamespace ? '|stub=yes' : '');
+ break;
+ default: // ffd, rfd
+ break;
+ }
+ notifytext += '|1=' + Morebits.pageNameNorm + '}} ~~~~';
+ return notifytext;
+ },
addToLog: function(params, initialContrib) {
if (!Twinkle.getPref('logXfdNominations') || Twinkle.getPref('noLogOnXfdNomination').includes(params.venue)) {
return;
@@ -1166,6 +1247,7 @@ Twinkle.xfd.callbacks = {
wikipedia_page.setFollowRedirect(true);
wikipedia_page.setCallbackParameters(params);
wikipedia_page.load(Twinkle.xfd.callbacks.afd.todaysList);
+
// Notification to first contributor
if (params.notifycreator) {
const thispage = new Morebits.wiki.Page(mw.config.get('wgPageName'));
@@ -1179,11 +1261,20 @@ Twinkle.xfd.callbacks = {
Twinkle.xfd.callbacks.addToLog(params, null);
}
- params.tagText = (params.noinclude ? '{{' : '{{') + (params.number === '' ? 'subst:afd|help=off' : 'subst:afdx|' +
- params.number + '|help=off') + (params.noinclude ? '}}\n' : '}}\n');
+ // Add AFD tag to article
+ params.tagText = Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(
+ params.noinclude, params.outcome, params.afdtarget, params.number
+ );
+
+ // If the selected outcome is merge, add {{Merge from}} to the target page
+ if (params.outcome === 'merging' && params.afdtarget) {
+ wikipedia_page = new Morebits.wiki.Page(params.afdtarget, 'Tagging the target page with {{Merge from}}');
+ wikipedia_page.setCallbackParameters(params);
+ wikipedia_page.load(Twinkle.xfd.callbacks.afd.tagTargetPageWithMergeFromTag);
+ }
if (pageobj.canEdit()) {
- // Remove some tags that should always be removed on AfD.
+ // Remove some tags that should always be removed on AfD.
text = text.replace(/\{\{\s*(dated prod|dated prod blp|Prod blp\/dated|Proposed deletion\/dated|prod2|Proposed deletion endorsed|Userspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
// Then, test if there are speedy deletion-related templates on the article.
const textNoSd = text.replace(/\{\{\s*(db(-\w*)?|delete|(?:hang|hold)[- ]?on)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/ig, '');
@@ -1204,6 +1295,47 @@ Twinkle.xfd.callbacks = {
Twinkle.xfd.callbacks.autoEditRequest(pageobj, params);
}
},
+ tagTargetPageWithMergeFromTag: function(pageobj) {
+ const statelem = pageobj.getStatusElement();
+ if (!pageobj.exists()) {
+ statelem.warn('Failed. Target page not found.');
+ return;
+ } else if (!pageobj.canEdit()) {
+ statelem.warn('Failed. Target page is protected from editing.');
+ return;
+ }
+
+ const params = pageobj.getCallbackParameters();
+ const tag = `{{Merge from |1=${Morebits.pageNameNorm} |target=${params.afdtarget} |afd=${Morebits.pageNameNorm + params.numbering} |date ={{subst:CURRENTMONTHNAME}} {{subst:CURRENTYEAR}} }}`;
+
+ const wikipage = new Morebits.wikitext.Page(pageobj.getPageText());
+ const text = wikipage.insertAfterTemplates(tag, Twinkle.hatnoteRegex).getText();
+ pageobj.setPageText(text);
+
+ pageobj.setEditSummary('Nominated for merging; see [[:' + params.discussionpage + ']].');
+ pageobj.setCreateOption('nocreate');
+ pageobj.save();
+ },
+ generateArticleTagWikitext: function(noinclude, outcome, afdtarget, number) {
+ let noIncludeStart = '';
+ let noIncludeEnd = '';
+ if (noinclude) {
+ noIncludeStart = '';
+ noIncludeEnd = '';
+ }
+
+ let templateAndParams = '';
+ const outcomeParam = outcome !== 'deletion' ? '|outcome=' + outcome : '';
+ const targetParam = afdtarget ? '|target=' + afdtarget : '';
+ const isFirstNomination = number === '';
+ if (isFirstNomination) {
+ templateAndParams = 'subst:afd|help=off' + outcomeParam + targetParam;
+ } else {
+ templateAndParams = 'subst:afdx|' + number + '|help=off' + outcomeParam + targetParam;
+ }
+
+ return noIncludeStart + '{{' + templateAndParams + '}}' + noIncludeEnd + '\n';
+ },
discussionPage: function(pageobj) {
const params = pageobj.getCallbackParameters();
diff --git a/tests/twinklexfd.test.js b/tests/twinklexfd.test.js
index c895b249d..aea3fe692 100644
--- a/tests/twinklexfd.test.js
+++ b/tests/twinklexfd.test.js
@@ -109,4 +109,181 @@ describe('modules/twinklexfd', () => {
expect(Twinkle.xfd.insertRMTR(pageWikitext, wikitextToInsert)).toBe(expected);
});
});
+
+ describe('generateArticleTagWikitext', () => {
+ test('deletion, 1st nomination', () => {
+ const noinclude = false;
+ const outcome = 'deletion';
+ const afdtarget = '';
+ const number = '';
+ const expected = '{{subst:afd|help=off}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('deletion, 1st nomination, noinclude', () => {
+ const noinclude = true;
+ const outcome = 'deletion';
+ const afdtarget = '';
+ const number = '';
+ const expected = '{{subst:afd|help=off}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('deletion, nth nomination', () => {
+ const noinclude = false;
+ const outcome = 'deletion';
+ const afdtarget = '';
+ const number = '24th';
+ const expected = '{{subst:afdx|24th|help=off}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('merging, 1st nomination, blank target', () => {
+ const noinclude = false;
+ const outcome = 'merging';
+ const afdtarget = '';
+ const number = '';
+ const expected = '{{subst:afd|help=off|outcome=merging}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('merging, 1st nomination, target specified', () => {
+ const noinclude = false;
+ const outcome = 'merging';
+ const afdtarget = 'TargetPage';
+ const number = '';
+ const expected = '{{subst:afd|help=off|outcome=merging|target=TargetPage}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('merging, nth nomination, target specified', () => {
+ const noinclude = false;
+ const outcome = 'merging';
+ const afdtarget = 'TargetPage';
+ const number = '4th';
+ const expected = '{{subst:afdx|4th|help=off|outcome=merging|target=TargetPage}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('redirect, 1st nomination, blank target', () => {
+ const noinclude = false;
+ const outcome = 'redirecting';
+ const afdtarget = '';
+ const number = '';
+ const expected = '{{subst:afd|help=off|outcome=redirecting}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('redirect, 1st nomination, target specified', () => {
+ const noinclude = false;
+ const outcome = 'redirecting';
+ const afdtarget = 'TargetPage';
+ const number = '';
+ const expected = '{{subst:afd|help=off|outcome=redirecting|target=TargetPage}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ test('draftify, 1st nomination', () => {
+ const noinclude = false;
+ const outcome = 'draftification';
+ const afdtarget = '';
+ const number = '';
+ const expected = '{{subst:afd|help=off|outcome=draftification}}\n';
+ expect(Twinkle.xfd.callbacks.afd.generateArticleTagWikitext(noinclude, outcome, afdtarget, number)).toBe(expected);
+ });
+ });
+
+ describe('generateUserTalkNoticeWikitext', () => {
+ test('afd, deletion, 1st nomination', () => {
+ const params = {};
+ params.venue = 'afd';
+ params.outcome = 'deletion';
+ params.afdtarget = '';
+ params.numbering = '';
+ params.xfdcat = '?';
+ params.tfdtarget = undefined;
+ params.action = undefined;
+ mw.config.set('wgNamespaceNumber', 0);
+ Morebits.pageNameNorm = 'NovemTest110';
+ const expected = '\n{{subst:afd notice|1=NovemTest110}} ~~~~';
+ expect(Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params)).toBe(expected);
+ });
+ test('afd, deletion, nth nomination', () => {
+ const params = {};
+ params.venue = 'afd';
+ params.outcome = 'deletion';
+ params.afdtarget = '';
+ params.numbering = ' (4th nomination)';
+ params.xfdcat = '?';
+ params.tfdtarget = undefined;
+ params.action = undefined;
+ mw.config.set('wgNamespaceNumber', 0);
+ Morebits.pageNameNorm = 'NovemTest110';
+ const expected = '\n{{subst:afd notice|order= (4th nomination)|1=NovemTest110}} ~~~~';
+ expect(Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params)).toBe(expected);
+ });
+ test('afd, merging, 1st nomination, blank target', () => {
+ const params = {};
+ params.venue = 'afd';
+ params.outcome = 'merging';
+ params.afdtarget = '';
+ params.numbering = '';
+ params.xfdcat = '?';
+ params.tfdtarget = undefined;
+ params.action = undefined;
+ mw.config.set('wgNamespaceNumber', 0);
+ Morebits.pageNameNorm = 'NovemTest110';
+ const expected = '\n{{subst:afd notice|outcome=merging|1=NovemTest110}} ~~~~';
+ expect(Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params)).toBe(expected);
+ });
+ test('afd, merging, 1st nomination, with target', () => {
+ const params = {};
+ params.venue = 'afd';
+ params.outcome = 'merging';
+ params.afdtarget = 'Testing 123';
+ params.numbering = '';
+ params.xfdcat = '?';
+ params.tfdtarget = undefined;
+ params.action = undefined;
+ mw.config.set('wgNamespaceNumber', 0);
+ Morebits.pageNameNorm = 'NovemTest110';
+ const expected = '\n{{subst:afd notice|outcome=merging|target=Testing 123|1=NovemTest110}} ~~~~';
+ expect(Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params)).toBe(expected);
+ });
+ test('afd, redirecting, 1st nomination, blank target', () => {
+ const params = {};
+ params.venue = 'afd';
+ params.outcome = 'redirecting';
+ params.afdtarget = '';
+ params.numbering = '';
+ params.xfdcat = '?';
+ params.tfdtarget = undefined;
+ params.action = undefined;
+ mw.config.set('wgNamespaceNumber', 0);
+ Morebits.pageNameNorm = 'NovemTest110';
+ const expected = '\n{{subst:afd notice|outcome=redirecting|1=NovemTest110}} ~~~~';
+ expect(Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params)).toBe(expected);
+ });
+ test('afd, redirecting, 1st nomination, with target', () => {
+ const params = {};
+ params.venue = 'afd';
+ params.outcome = 'redirecting';
+ params.afdtarget = 'Testing 123';
+ params.numbering = '';
+ params.xfdcat = '?';
+ params.tfdtarget = undefined;
+ params.action = undefined;
+ mw.config.set('wgNamespaceNumber', 0);
+ Morebits.pageNameNorm = 'NovemTest110';
+ const expected = '\n{{subst:afd notice|outcome=redirecting|target=Testing 123|1=NovemTest110}} ~~~~';
+ expect(Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params)).toBe(expected);
+ });
+ test('afd, draftification, 1st nomination', () => {
+ const params = {};
+ params.venue = 'afd';
+ params.outcome = 'draftification';
+ params.afdtarget = '';
+ params.numbering = '';
+ params.xfdcat = '?';
+ params.tfdtarget = undefined;
+ params.action = undefined;
+ mw.config.set('wgNamespaceNumber', 0);
+ Morebits.pageNameNorm = 'NovemTest110';
+ const expected = '\n{{subst:afd notice|outcome=draftification|1=NovemTest110}} ~~~~';
+ expect(Twinkle.xfd.callbacks.generateUserTalkNoticeWikitext(params)).toBe(expected);
+ });
+ // TODO: add tests for tfd, cfd, mfd, ffd, rfd
+ });
});