local frame = mw.getCurrentFrame()
local title = frame and frame.args and frame.args.module or 'Transcluder'
local T = require( 'Module:' .. title )
local ScribuntoUnit = require('Module:ScribuntoUnit')
local Suite = ScribuntoUnit:new()

function Suite:testCategories()
	self:assertThrows( function() T.getCategories() end )
	self:assertThrows( function() T.getCategories({}) end )
	self:assertThrows( function() T.getCategories(false) end )

	self:assertDeepEquals( {}, T.getCategories('') )
	self:assertDeepEquals( {}, T.getCategories('a') )
	self:assertDeepEquals( {'[[Category:A]]'}, T.getCategories('[[Category:A]]') )
	self:assertDeepEquals( {'[[Category:A|]]'}, T.getCategories('[[Category:A|]]') )
	self:assertDeepEquals( {'[[Category:A| ]]'}, T.getCategories('[[Category:A| ]]') )
	self:assertDeepEquals( {'[[Category:A|B]]'}, T.getCategories('[[Category:A|B]]') )
	self:assertDeepEquals( {'[[Category:A]]','[[Category:B]]'}, T.getCategories('[[Category:A]][[Category:B]]') )
	self:assertDeepEquals( {'[[Category:A]]','[[Category:B]]'}, T.getCategories('\n[[Category:A]]\n[[Category:B]]\nc') )
	self:assertDeepEquals( {}, T.getCategories('[[Category:A]]', 0) )
	self:assertDeepEquals( {'[[Category:B]]'}, T.getCategories('[[Category:A]][[Category:B]]', 2 ) )
	self:assertDeepEquals( {'[[Category:B]]','[[Category:C]]'}, T.getCategories('[[Category:A]][[Category:B]][[Category:C]]', '2-3') )
	self:assertDeepEquals( {'[[Category:B]]'}, T.getCategories('[[Category:A]][[Category:B]][[Category:C]]', 'B') )
	self:assertDeepEquals( {'[[Category:A]]','[[Category:C]]'}, T.getCategories('[[Category:A]][[Category:B]][[Category:C]]', '-B') )

	self:assertEquals( '[[Category:A]]', T.get('Module:Transcluder/test#Categories', { categories = 1 } ) )
	self:assertEquals( '[[Category:B]]', T.get('Module:Transcluder/test#Categories', { categories = 2 } ) )
	self:assertEquals( '[[Category:A]]\n\n[[Category:C]]', T.get('Module:Transcluder/test#Categories', { categories = '-B' } ) )
end

function Suite:testErrors()
	self:assertThrows( function() T.get() end, 'No page given' )
	self:assertThrows( function() T.get('') end, 'No page given' )
	self:assertThrows( function() T.get(' ') end, 'No page given' )
	self:assertThrows( function() T.get('Fake') end, "Page 'Fake' not found" )
	self:assertThrows( function() T.get('Module:Transcluder/test#Fake') end, "Section 'Fake' not found" )
end

function Suite:testFiles()
	self:assertThrows( function() T.getFiles() end )
	self:assertThrows( function() T.getFiles({}) end )
	self:assertThrows( function() T.getFiles(false) end )

	self:assertDeepEquals( {}, T.getFiles('') )
	self:assertDeepEquals( {}, T.getFiles('a') )
	self:assertDeepEquals( {'[[File:A.png]]'}, T.getFiles('[[File:A.png]]') )
	self:assertDeepEquals( {'[[Image:A.png]]'}, T.getFiles('[[Image:A.png]]') )
	self:assertDeepEquals( {'[[File:A.png]]','[[File:B.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]]') )
	self:assertDeepEquals( {'[[File:A.png]]','[[File:B.png]]'}, T.getFiles('\n[[File:A.png]]\n[[File:B.png]]\nc') )
	self:assertDeepEquals( {}, T.getFiles('[[File:A.png]]', 0 ) )
	self:assertDeepEquals( {'[[File:B.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]]', 2 ) )
	self:assertDeepEquals( {'[[File:A.png]]','[[File:C.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', '-2' ) )
	self:assertDeepEquals( {'[[File:B.png]]','[[File:C.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', '2-3') )
	self:assertDeepEquals( {'[[File:A.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', 'A.png') )
	self:assertDeepEquals( {'[[File:B.png]]','[[File:C.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', '-A.png') )
	self:assertDeepEquals( {'[[File:A.png]]','[[File:C.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', 'A.png, C.png') )
	self:assertDeepEquals( {'[[File:B.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', '-A.png, C.png') )

	self:assertDeepEquals( {'[[File:B.png]]','[[File:C.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', -1 ) )
	self:assertDeepEquals( {'[[File:A.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', '-2-3' ) )
	self:assertDeepEquals( {'[[File:A.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', { [1] = true } ) )
	self:assertDeepEquals( {'[[File:B.png]]','[[File:C.png]]'}, T.getFiles('[[File:A.png]][[File:B.png]][[File:C.png]]', { [1] = false } ) )

	self:assertEquals( '[[File:A.png]]ab', T.get('Module:Transcluder/test#Files', { files = 1 } ) )
	self:assertEquals( 'a[[File:C.png]]b', T.get('Module:Transcluder/test#Files', { files = 2 } ) )
end

function Suite:testGet()
	self:assertEquals( '[[File:A.png]]\nb\n*c\n*d\n{|\n|e\n|}\n[[File:f.png]]\ng\n#h\n#i\nj\n{|\n|k\n|}\nl', T.get('Module:Transcluder/test#Get') )
	self:assertEquals( 'b\n\n[[File:f.png]]\ng\n#h\n#i\nj\n{|\n|k\n|}\nl', T.get('Module:Transcluder/test#Get', { files = 2, tables = 2, lists = 2 } ) )
end

function Suite:testInclude()
	self:assertEquals( 'ac', T.get('Module:Transcluder/test#Include') )
end

function Suite:testLead()
	self:assertEquals( "This '''test''' page interacts with [[Module:Transcluder/testcases]].", T.get('Module:Transcluder/test#') )
	self:assertEquals( 'This test page interacts with [[Module:Transcluder/testcases]].', T.get('Module:Transcluder/test#', { noBold = true } ) )
end

function Suite:testLinks()
	self:assertEquals( 'a b c d e', T.get('Module:Transcluder/test#Links', { noLinks = true } ) )
end

function Suite:testLists()
	self:assertDeepEquals( {}, T.getLists('') )
	self:assertDeepEquals( {}, T.getLists('a') )
	self:assertDeepEquals( {'*a\n*b'}, T.getLists('*a\n*b') )
	self:assertDeepEquals( {'*b\n*c'}, T.getLists('a\n*b\n*c\nd') )
	self:assertDeepEquals( {'*b\n*c','#e\n#f'}, T.getLists('a\n*b\n*c\nd\n#e\n#f\ng') )
	self:assertDeepEquals( {'#e\n#f'}, T.getLists('a\n*b\n*c\nd\n#e\n#f\ng', 2 ) )
	self:assertDeepEquals( {'#e\n#f','*h\n*i'}, T.getLists('a\n*b\n*c\nd\n#e\n#f\ng\n*h\n*i', '2-3' ) )

	self:assertEquals( '*b\n*c\n\n#e\n#f', T.get('Module:Transcluder/test#Lists', { only = 'lists' } ) )
	self:assertEquals( '#e\n#f', T.get('Module:Transcluder/test#Lists', { only = 'lists', lists = 2 } ) )
end

function Suite:testOnly()
	self:assertEquals( '{|\n|e\n|}\n\n{|\n|k\n|}\n\n*c\n*d\n\n#h\n#i', T.get('Module:Transcluder/test#Only', { only = 'tables, lists' } ) )
	self:assertEquals( '*c\n*d\n\n#h\n#i\n\n{|\n|e\n|}\n\n{|\n|k\n|}', T.get('Module:Transcluder/test#Only', { only = 'lists, tables' } ) )
	self:assertEquals( '*c\n*d\n\n{|\n|e\n|}\n\n{|\n|k\n|}', T.get('Module:Transcluder/test#Only', { only = 'lists, tables', lists = 1 } ) )
end

function Suite:testParagraphs()
	self:assertDeepEquals( {'a'}, T.getParagraphs('a') )
	self:assertDeepEquals( {'a{{b}}'}, T.getParagraphs('a{{b}}') )
	self:assertDeepEquals( {'{{a}}b'}, T.getParagraphs('{{a}}b') )
	self:assertDeepEquals( {}, T.getParagraphs('{{a}}') )
	self:assertDeepEquals( {}, T.getParagraphs('{{a\n|b=c}}') )
	self:assertDeepEquals( {}, T.getParagraphs('{{a}}\n\n{{b}}\n\n{{c}}') )
	self:assertDeepEquals( {'a'}, T.getParagraphs('a\n\n{{b}}') )
	self:assertDeepEquals( {'b'}, T.getParagraphs('{{a}}\n\nb') )
	self:assertDeepEquals( {'{{a}}b{{c}}'}, T.getParagraphs('{{a}}b{{c}}') )
	self:assertDeepEquals( {'a','b','c'}, T.getParagraphs('a\n\nb\n\nc') )
	self:assertDeepEquals( {'a','c'}, T.getParagraphs('a\n\n{{b}}\n\nc') )
	self:assertDeepEquals( {'a','c','d','e'}, T.getParagraphs('a\n\nb\n\nc\n\nd\n\ne', '1,3-5' ) )
	self:assertDeepEquals( {'e'}, T.getParagraphs('{{a}}\n{{b}}\n{{c}}\n{{d}}\ne', 1 ) )

	self:assertEquals( '[[File:Name.jpg|thumb|a]]\na\n{|\n|b\n|}\n\n{{e}}', T.get('Module:Transcluder/test#Paragraphs', { paragraphs = 1 } ) )
	self:assertEquals( 'a\n\n{{b}} c {{d}}', T.get('Module:Transcluder/test#Paragraphs', { only = 'paragraphs' } ) )
	self:assertEquals( 'a', T.get('Module:Transcluder/test#Paragraphs', { only = 'paragraphs', paragraphs = 1 } ) )
	self:assertEquals( '{{b}} c {{d}}', T.get('Module:Transcluder/test#Paragraphs', { only = 'paragraphs', paragraphs = 2 } ) )
end

function Suite:testParameters()
	self:assertDeepEquals( {}, T.getParameters('{{a}}', 0 ) )
	self:assertDeepEquals( {}, T.getParameters('{{a}}', 1 ) )
	self:assertDeepEquals( {}, T.getParameters('{{a|b}}', 2 ) )
	self:assertDeepEquals( {}, T.getParameters('{{a|b=c}}', 1 ) )
	self:assertDeepEquals( {}, T.getParameters('{{a|b=c}}', 'd' ) )
	self:assertDeepEquals( {['b']='c'}, T.getParameters('{{a|b=c|d=e}}', 'b' ) )
	self:assertDeepEquals( {['b']='2%'}, T.getParameters('{{a|b=2%}}', 'b' ) )
	self:assertDeepEquals( {['d']='e'}, T.getParameters('{{aa\n|\nb=c\n|d=e\n}}', 'd' ) )
	self:assertDeepEquals( {['f']='g'}, T.getParameters('{{ a | b = c | f = g }}', ' f ' ) )
	self:assertDeepEquals( {['b']='c',['d']='e'}, T.getParameters('{{a|b=c|d=e}}', 'b,d' ) )
	self:assertDeepEquals( {['b']='{{c|d=e}}'}, T.getParameters('{{a|b={{c|d=e}}}}', 'b' ) )
	self:assertDeepEquals( {['b']='{{c|d=2%}}'}, T.getParameters('{{a|b={{c|d=2%}}}}', 'b' ) )
	self:assertDeepEquals( {['b']='<div class="c">d</div>'}, T.getParameters('{{a|b=<div class="c">d</div>}}', 'b' ) )
	self:assertDeepEquals( {['b']='{{c|[[d|e]]}}'}, T.getParameters('{{a|b={{c|[[d|e]]}}}}', 'b' ) )
	self:assertDeepEquals( {['b']='[[c|d]]'}, T.getParameters('{{a|b=[[c|d]]}}', 'b' ) )
	self:assertDeepEquals( {[1]='f'}, T.getParameters('{{a|b=c|d=e|f}}', 1 ) )
	self:assertDeepEquals( {[1]='d',[2]='e',[3]='h'}, T.getParameters('{{a|b=c|d|e|f=g|h}}', '1-3' ) )

	self:assertEquals( 'd', T.get('Module:Transcluder/test#Parameters', { only = 'parameters', parameters = 'b' } ) )
	self:assertEquals( 'c', T.get('Module:Transcluder/test#Parameters', { only = 'parameters', parameters = 'b', templates = 'aa' } ) )
	self:assertEquals( 'd', T.get('Module:Transcluder/test#Parameters', { only = 'parameters', parameters = 'b', templates = 'bb' } ) )
end

function Suite:testReferences()
	self:assertDeepEquals( {}, T.getReferences('a') )
	self:assertDeepEquals( {'<ref>b</ref>'}, T.getReferences('a<ref>b</ref>') )
	self:assertDeepEquals( {}, T.getReferences('a<ref>b</ref>', 0) )
	self:assertDeepEquals( {}, T.getReferences('a<ref name="b" />') )
	self:assertDeepEquals( {'<ref>d</ref>'}, T.getReferences('a<ref>b</ref>c<ref>d</ref>', 2) )
	self:assertDeepEquals( {'<ref name="b">c</ref>','<ref>e</ref>'}, T.getReferences('a<ref name="b">c</ref>d<ref name="b" /><ref>e</ref>') )
	self:assertDeepEquals( {'<ref name="b">c</ref>'}, T.getReferences('a<ref name="b">c</ref>d<ref name="b" /><ref>e</ref>', 'b') )

	self:assertEquals( 'acfg', T.get('Module:Transcluder/test#References', { references = 0 } ) )
	self:assertEquals( '<ref>b</ref>\n\n<ref name="d">e</ref>\n\n<ref name="h" group="i">j</ref>', T.get('Module:Transcluder/test', { only = 'references' } ) )
	self:assertEquals( '<ref>b</ref>\n\n<ref name="Module:Transcluder/test d">e</ref>\n\n<ref name="Module:Transcluder/test h">j</ref>', T.get('Module:Transcluder/test', { only = 'references', fixReferences = true } ) )
end

function Suite:testSection()
	self:assertThrows( function() T.getSection('a', 'a') end, "Section 'a' not found" )
	self:assertThrows( function() T.getSection('==z==', 'z') end, "Section 'z' is empty" )

	self:assertEquals( 'b', T.getSection('==a==\nb', 'a') )
	self:assertEquals( 'b', T.getSection('==a==\nb\n==c==\nd', 'a') )
	self:assertEquals( 'b\n===c===\nd', T.getSection('==a==\nb\n===c===\nd', 'a') )
	self:assertEquals( 'd', T.getSection('==a==\nb\n===c===\nd', 'c') )

	self:assertEquals( 'a\n===Subsection===\nb', T.get('Module:Transcluder/test#Section') )
	self:assertEquals( 'b', T.get('Module:Transcluder/test#Subsection') )
	self:assertEquals( 'a', T.get('Module:Transcluder/test#Section', { sections = 0 } ) )
end

function Suite:testSections()
	self:assertEquals( "This '''test''' page interacts with [[Module:Transcluder/testcases]].", T.get('Module:Transcluder/test', { sections = 0 } ) )
	self:assertEquals( 'a\n===Subsection===\nb', T.get('Module:Transcluder/test#Section') )
	self:assertEquals( 'a', T.get('Module:Transcluder/test#Section', { sections = 0 } ) )
	self:assertEquals( 'a', T.get('Module:Transcluder/test#Section', { sections = 2 } ) )
	self:assertEquals( 'a', T.get('Module:Transcluder/test#Section', { sections = 'Fake' } ) )
	self:assertEquals( 'a\n===Subsection===\nb', T.get('Module:Transcluder/test#Section', { sections = 1 } ) )
	self:assertEquals( 'a\n===Subsection===\nb', T.get('Module:Transcluder/test#Section', { sections = 'Subsection' } ) )
	self:assertEquals( 'd', T.get('Module:Transcluder/test#Subsection with [[link]]' ) )
	self:assertEquals( 'e\n===Subsection===\nf', T.get('Module:Transcluder/test#Section with (parenthesis)' ) )

	-- <section> tags
	self:assertThrows( function() T.get('Module:Transcluder/test#a') end, "Section tag 'a' is empty" )
	self:assertEquals( 'b', T.get('Module:Transcluder/test#b' ) )
	self:assertEquals( '{|\n!c\n|}', T.get('Module:Transcluder/test#c' ) )
end

function Suite:testSelfLink()
	self:assertEquals( "This '''test''' page interacts with Module:Transcluder/testcases.", T.get('Module:Transcluder/test', { noSelfLinks = true, sections = 0 } ) )
	self:assertEquals( 'Module:Transcluder/testcases module:Transcluder/testcases a a', T.get('Module:Transcluder/test#Self links', { noSelfLinks = true, sections = 0 } ) )
end

function Suite:testTables()
	self:assertEquals( '{|\n!b\n|}\n\n{|\n|d\n|}\n\n{|id="e"\n|e\n|}', T.get('Module:Transcluder/test#Tables', { only = 'tables' } ) )
	self:assertEquals( '{|\n!b\n|}', T.get('Module:Transcluder/test#Tables', { only = 'tables', tables = 1 } ) )
	self:assertEquals( '{|\n|d\n|}', T.get('Module:Transcluder/test#Tables', { only = 'tables', tables = 2 } ) )
	self:assertEquals( '{|\n!b\n|}\n\n{|id="e"\n|e\n|}', T.get('Module:Transcluder/test#Tables', { only = 'tables', tables = '1,3' } ) )
	self:assertEquals( '{|\n|d\n|}\n\n{|id="e"\n|e\n|}', T.get('Module:Transcluder/test#Tables', { only = 'tables', tables = '2-3' } ) )
	self:assertEquals( '{|id="e"\n|e\n|}', T.get('Module:Transcluder/test#Tables', { only = 'tables', tables = 'e' } ) )
end

function Suite:testTemplates()
	self:assertDeepEquals( {'{{b}}','{{c}}','{{d}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e' ) )
	self:assertDeepEquals( {'{{c}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', 2 ) )
	self:assertDeepEquals( {'{{d}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', 'D' ) )
	self:assertDeepEquals( {'{{ b \n | c = d \n}}'}, T.getTemplates( 'a{{ b \n | c = d \n}}e', 'b' ) )
	self:assertDeepEquals( {'{{a|b={{c|d=e}}}}'}, T.getTemplates( '{{a|b={{c|d=e}}}}', 'a' ) )
	self:assertDeepEquals( {'{{b}}','{{c}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', '-d' ) )
	self:assertDeepEquals( {'{{c}}','{{d}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', 'c,d' ) )
	self:assertDeepEquals( {'{{b}}','{{d}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', '1,d' ) )
	self:assertDeepEquals( {'{{c}}','{{d}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', { ['c'] = true, ['d'] = true } ) )
	self:assertDeepEquals( {'{{b}}','{{d}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', { [1] = true, ['d'] = true } ) )
	self:assertDeepEquals( {'{{c}}','{{d}}'}, T.getTemplates( 'a{{b}}{{c}}{{d}}e', { [1] = false } ) )

	self:assertEquals( '{{b}}\n\n{{c}}\n\n{{d}}', T.get('Module:Transcluder/test#Templates', { only = 'templates' } ) )
	self:assertEquals( '{{c}}', T.get('Module:Transcluder/test#Templates', { only = 'templates', templates = 2 } ) )
	self:assertEquals( '{{d}}', T.get('Module:Transcluder/test#Templates', { only = 'templates', templates = 'd' } ) )
	self:assertEquals( '{{c}}\n\n{{d}}', T.get('Module:Transcluder/test#Templates', { only = 'templates', templates = 'c,d' } ) )
end

return Suite