mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-12-04 18:58:37 +00:00
25019d7f55
Our encoding for the hrefs like "./Foo" that we send to Parsoid differed slightly from how Parsoid outputs them, so to avoid dirty diffs, we had to store the original ones we received from Parsoid and send them back if they were unchanged. Change the encoding to match Parsoid's exactly (by referring to the Parsoid source code), and then remove 'rawTitle'/'origTitle'. On a historical note, 'rawTitle'/'origTitle' were originally added to fix other issues with links, which I hope are long behind us: *bb45d984ca
(T145978) *fda2e6c1b5
(T44140) Follow-up to362df66b47
, which removed some other old stuff from the handling of Parsoid links. Bug: T325766 Change-Id: I0ad0a655380eb2fb29b5ac01e2e399ac550ce34a
126 lines
8.9 KiB
JavaScript
126 lines
8.9 KiB
JavaScript
/*!
|
|
* Parsoid utilities tests.
|
|
*
|
|
* @copyright 2011-2020 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
QUnit.module( 've.utils.parsoid', ve.test.utils.newMwEnvironment() );
|
|
|
|
QUnit.test( 'reduplicateStyles/deduplicateStyles', ( assert ) => {
|
|
// Test cases based on this page and the templates there:
|
|
// https://en.wikipedia.beta.wmflabs.org/wiki/Table_templated
|
|
const stylesCases = [
|
|
{
|
|
msg: 'styles are deduplicated',
|
|
deduplicated: `<span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[]],"dsr":[0,107,null,null]}' data-mw='{"parts":[{"template":{"target":{"wt":"table start","href":"./Template:Table_start"},"params":{},"i":0}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Hello"},"2":{"wt":"good"}},"i":1}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Goodbye"},"2":{"wt":"bad"}},"i":2}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Welcome"},"2":{"wt":"good"}},"i":3}},"\\n",{"template":{"target":{"wt":"table end","href":"./Template:Table_end"},"params":{},"i":4}}]}'>
|
|
</span><table class="wikitable" about="#mwt1">
|
|
<tbody><tr>
|
|
<td class="good"><style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt4" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>Hello</td></tr>
|
|
<tr>
|
|
<td class="bad"><link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r5432" about="#mwt7" typeof="mw:Extension/templatestyles" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'/>Goodbye</td></tr>
|
|
<tr>
|
|
<td class="good"><link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r5432" about="#mwt10" typeof="mw:Extension/templatestyles" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'/>Welcome</td></tr>
|
|
</tbody></table>`,
|
|
reduplicated: `<span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[]],"dsr":[0,107,null,null]}' data-mw='{"parts":[{"template":{"target":{"wt":"table start","href":"./Template:Table_start"},"params":{},"i":0}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Hello"},"2":{"wt":"good"}},"i":1}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Goodbye"},"2":{"wt":"bad"}},"i":2}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Welcome"},"2":{"wt":"good"}},"i":3}},"\\n",{"template":{"target":{"wt":"table end","href":"./Template:Table_end"},"params":{},"i":4}}]}'>
|
|
</span><table class="wikitable" about="#mwt1">
|
|
<tbody><tr>
|
|
<td class="good"><style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt4" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>Hello</td></tr>
|
|
<tr>
|
|
<td class="bad"><style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt7" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>Goodbye</td></tr>
|
|
<tr>
|
|
<td class="good"><style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt10" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>Welcome</td></tr>
|
|
</tbody></table>`
|
|
},
|
|
{
|
|
msg: 'styles in fosterable positions are NOT deduplicated, but they are emptied',
|
|
deduplicated: `<span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[]],"dsr":[0,107,null,null]}' data-mw='{"parts":[{"template":{"target":{"wt":"table start","href":"./Template:Table_start"},"params":{},"i":0}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Hello"},"2":{"wt":"good"}},"i":1}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Goodbye"},"2":{"wt":"bad"}},"i":2}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Welcome"},"2":{"wt":"good"}},"i":3}},"\\n",{"template":{"target":{"wt":"table end","href":"./Template:Table_end"},"params":{},"i":4}}]}'>
|
|
</span><table class="wikitable" about="#mwt1">
|
|
<tbody><tr>
|
|
<style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt4" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>
|
|
<td class="good">Hello</td></tr>
|
|
<tr>
|
|
<style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt7" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'></style>
|
|
<td class="bad">Goodbye</td></tr>
|
|
<tr>
|
|
<style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt10" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'></style>
|
|
<td class="good">Welcome</td></tr>
|
|
</tbody></table>`,
|
|
reduplicated: `<span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[{"k":"1"},{"k":"2"}],[]],"dsr":[0,107,null,null]}' data-mw='{"parts":[{"template":{"target":{"wt":"table start","href":"./Template:Table_start"},"params":{},"i":0}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Hello"},"2":{"wt":"good"}},"i":1}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Goodbye"},"2":{"wt":"bad"}},"i":2}},"\\n",{"template":{"target":{"wt":"table row","href":"./Template:Table_row"},"params":{"1":{"wt":"Welcome"},"2":{"wt":"good"}},"i":3}},"\\n",{"template":{"target":{"wt":"table end","href":"./Template:Table_end"},"params":{},"i":4}}]}'>
|
|
</span><table class="wikitable" about="#mwt1">
|
|
<tbody><tr>
|
|
<style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt4" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>
|
|
<td class="good">Hello</td></tr>
|
|
<tr>
|
|
<style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt7" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>
|
|
<td class="bad">Goodbye</td></tr>
|
|
<tr>
|
|
<style data-mw-deduplicate="TemplateStyles:r5432" typeof="mw:Extension/templatestyles" about="#mwt10" data-mw='{"name":"templatestyles","attrs":{"src":"Table row/styles.css"}}'>.mw-parser-output .good{background:#9EFF9E}.mw-parser-output .bad{background:#FFC7C7}</style>
|
|
<td class="good">Welcome</td></tr>
|
|
</tbody></table>`
|
|
}
|
|
];
|
|
|
|
stylesCases.forEach( ( caseItem ) => {
|
|
const doc = ve.parseXhtml( caseItem.deduplicated );
|
|
|
|
// Test that we can re-duplicate styles, which were de-duplicated in Parsoid HTML
|
|
mw.libs.ve.reduplicateStyles( doc.body );
|
|
assert.equalDomElement(
|
|
doc.body,
|
|
ve.parseXhtml( caseItem.reduplicated ).body,
|
|
caseItem.msg + ' (reduplicated)'
|
|
);
|
|
|
|
// Test that we can de-duplicate styles again, producing a result identical to the Parsoid HTML
|
|
mw.libs.ve.deduplicateStyles( doc.body );
|
|
assert.equalDomElement(
|
|
doc.body,
|
|
ve.parseXhtml( caseItem.deduplicated ).body,
|
|
caseItem.msg + ' (deduplicated)'
|
|
);
|
|
} );
|
|
} );
|
|
|
|
QUnit.test( 'getTargetDataFromHref', ( assert ) => {
|
|
const doc = ve.parseXhtml( '<p></p>' );
|
|
const hrefCases = [
|
|
{
|
|
/* eslint-disable no-script-url */
|
|
msg: 'Invalid protocol is handled as internal link',
|
|
href: 'javascript:alert()',
|
|
expectedInfo: {
|
|
title: 'javascript:alert()',
|
|
isInternal: true
|
|
}
|
|
/* eslint-enable no-script-url */
|
|
},
|
|
{
|
|
msg: 'Invalid protocol is handled as internal link',
|
|
href: 'not-a-protocol:Some%20text',
|
|
expectedInfo: {
|
|
title: 'not-a-protocol:Some text',
|
|
isInternal: true
|
|
}
|
|
},
|
|
{
|
|
msg: 'Valid protocol is handled as external link',
|
|
href: 'https://example.net/',
|
|
expectedInfo: {
|
|
isInternal: false
|
|
}
|
|
},
|
|
{
|
|
msg: 'Valid protocol is handled as external link',
|
|
href: 'mailto:example@example.net',
|
|
expectedInfo: {
|
|
isInternal: false
|
|
}
|
|
}
|
|
];
|
|
hrefCases.forEach( ( caseItem ) => {
|
|
const actualInfo = mw.libs.ve.getTargetDataFromHref( caseItem.href, doc );
|
|
assert.deepEqual( actualInfo, caseItem.expectedInfo, caseItem.msg );
|
|
} );
|
|
} );
|