--- /dev/null
+!! hooks
+source
+!! endhooks
+
+!! test
+Non-existent language
+!!input
+<source lang="doesnotexist">
+foobar
+</source>
+!! result
+<div class="mw-highlight mw-content-ltr" dir="ltr"><pre>foobar</pre></div>
+
+!! end
+
+!! test
+No language specified
+!! wikitext
+<source>
+foo
+</source>
+!! html
+<div class="mw-highlight mw-content-ltr" dir="ltr"><pre>foo</pre></div>
+
+!! end
+
+!! test
+No language specified (no wellformed xml)
+!! config
+!! wikitext
+<source>
+bar
+</source>
+!! html
+<div class="mw-highlight mw-content-ltr" dir="ltr"><pre>bar</pre></div>
+
+!! end
+
+!! test
+XSS is escaped
+!!input
+<source lang="doesnotexist">
+<script>alert("pwnd")</script>
+<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
+<IMG
+SRC=javascript:alert(
+'XSS')
+\";alert('XSS');//
+</script><script>alert('XSS');</script>
+%253cscript%253ealert(document.cookie)%253c/script%253e
+</source>
+!! result
+<div class="mw-highlight mw-content-ltr" dir="ltr"><pre><script>alert("pwnd")</script>
+<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
+<IMG
+SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;
+&#39;&#88;&#83;&#83;&#39;&#41;
+\";alert('XSS');//
+</script><script>alert('XSS');</script>
+%253cscript%253ealert(document.cookie)%253c/script%253e</pre></div>
+
+!! end
+
+!! test
+XSS is escaped (inline)
+!!input
+<source lang="doesnotexist" inline>
+<script>alert("pwnd")</script>
+<IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>
+<IMG
+SRC=javascript:alert(
+'XSS')
+\";alert('XSS');//
+</script><script>alert('XSS');</script>
+%253cscript%253ealert(document.cookie)%253c/script%253e
+</source>
+!! result
+<p><code class="mw-highlight" dir="ltr"><script>alert("pwnd")</script> <IMG SRC=`javascript:alert("RSnake says, 'XSS'")`> <IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40; &#39;&#88;&#83;&#83;&#39;&#41; \";alert('XSS');// </script><script>alert('XSS');</script> %253cscript%253ealert(document.cookie)%253c/script%253e</code>
+</p>
+!! end
+
+!! test
+Default behaviour (inner is pre)
+!!input
+<source lang="javascript">
+var a;
+</source>
+!! result
+<div class="mw-highlight mw-content-ltr" dir="ltr"><pre><span></span><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span>
+</pre></div>
+
+!! end
+
+!! test
+Multiline <source/> in lists
+!!input
+* <source>a
+b</source>
+
+* foo <source>a
+b</source>
+!! html
+<ul><li> <div class="mw-highlight mw-content-ltr" dir="ltr"><pre>a
+b</pre></div></li></ul>
+<ul><li> foo <div class="mw-highlight mw-content-ltr" dir="ltr"><pre>a
+b</pre></div></li></ul>
+
+!! html+tidy
+<ul>
+<li>
+<div class="mw-highlight mw-content-ltr" dir="ltr">
+<pre>
+a
+b
+</pre></div>
+</li>
+</ul>
+<ul>
+<li>foo
+<div class="mw-highlight mw-content-ltr" dir="ltr">
+<pre>
+a
+b
+</pre></div>
+</li>
+</ul>
+!! end
+
+!! test
+Custom attributes
+!!input
+<source lang="javascript" id="foo" class="bar" dir="rtl" style="font-size: larger;">var a;</source>
+!! result
+<div id="foo" class="bar mw-highlight mw-content-rtl" dir="rtl" style="font-size: larger;"><pre><span></span><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span>
+</pre></div>
+
+!! end
+
+!! test
+Inline attribute (inline code)
+!!input
+Text <source lang="javascript" inline>var a;</source>.
+!! result
+<p>Text <code class="mw-highlight" dir="ltr"><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span></code>.
+</p>
+!! end
+
+!! test
+Enclose none (inline code)
+!!input
+Text <source lang="javascript" enclose="none">var a;</source>.
+!! result
+<p>Text <code class="mw-highlight" dir="ltr"><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span></code>.
+</p>
+!! end
+
+!! test
+Enclose with nowiki
+!! input
+{{#tag:syntaxhighlight|<nowiki>foo</nowiki>|lang="text"|inline=none}}
+!! result
+<p><code class="mw-highlight" dir="ltr">foo</code>
+</p>
+!! end