La documentation pour ce module peut être créée à Module:DropBox/Documentation

local p = {}
--[[
-- The main central module is mainly an installer of central libraries and a small demonstrator.
-- The main central module installs central libraries and bind the main and its sub-modules
-- local Central = p -- Save as MdSubTests.lua MdSubTests first minimal test fields from subnane to errors 20190903 2258.lua
-------------------------------|--------------|------------------------ typical length -------------------------|----------max| DODO
	-- Guideline : Convert these mini modules whith this kind of infos
	-- Guideline : some test like DropBoxCentralTry call the 2 modules DropBox and or CentralTry to diversify tests
	-- Guideline : divide the code in functions to test groups of : sought, known, sub modules calling 2 simple, missing.
	-- Guideline : submodules with or without : sought, known, sub modules calling 2 simple, missing.
	-- Guideline : test only one complete OK example and one case of each probable error
		return { case.subnane, case.sought, case.known, case.double, case.founds, case.missings } -- example
--	MWMW : means add a mw version in the table activity.MediaWiki_Versions = { ... }
--	COCO : is the present change point of Lua codage. hh
--]]

p.bind_all_sub_modules_test_cases { -- Test : Bind all sub-modules of the main module.
	{ ["subnane"] = "CentralTry",	['sought'] = "CentralTry;DropBox", 	['known'] = "CentralTry;DropBox",
		['missings'] = "CentralTry;DropBox", 	["founds"] = "nil",	['double'] = 1, },
	{ ["subnane"] = "DropBox",	['sought'] = "CentralTry;DropBox", 	['known'] = "CentralTry;DropBox", 	['double'] = 2,
		["founds"] = "nil",	['missings'] = "CentralTry;DropBox", },
	{ ["subnane"] = "DropBoxCentralTry",	['sought'] = "CentralTry;DropBox", 	['known'] = "CentralTry;DropBox", 	['double'] = 2,
		["founds"] = "nil",	['missings'] = "CentralTry;DropBox", },
	{ ["subnane"] = "CentralTry",	['sought'] = "CentralTry;DropBox", 	['known'] = "CentralTry;DropBox", 	['double'] = 1,
		["founds"] = "nil",	['missings'] = "CentralTry;DropBox", },
	{ ["subnane"] = "DropBox",	['sought'] = "CentralTry;DropBox", 	['known'] = "CentralTry;DropBox", 	['double'] = 1,
		["founds"] = "nil",	['missings'] = "CentralTry;DropBox", },
	{ ["subnane"] = "DropBoxCentralTry",	['sought'] = "CentralTry;DropBox", 	['known'] = "CentralTry;DropBox", 	['double'] = 2,
		["founds"] = "nil",	['missings'] = "CentralTry;DropBox", },
	{ ["subnane"] = "CentralTry",	['sought'] = "CentralTry;DropBox", 	['known'] = "CentralTry;DropBox", 	['double'] = 1,
		["founds"] = "nil",	['missings'] = "CentralTry;DropBox", },
	['sought']				= "DropBox;CentralTry;DropBoxCentralTry;TestpackG;LibraryTestpackGLibrary;CentralScool", -- Sought  submodules
	['known']				= "DropBox;CentralTry;DropBoxCentralTry;TestpackG;LibraryTestpackGLibrary;CentralScool", -- Tested submodules
}

tableview = {}			-- Object:tableview from 20170208

function tableview.form_one_case(case, tab_view) -- Default: Convert a case from test_group to rowGroup.
	local tocase = case -- {}
	return case
end -- function tableview.form_one_case(case)

function tableview.add_Row(case, tab_view) -- Default: Add a row to rowGroup.
	if (type(case) == "table") and (type(tab_view) == "table") and (type(tab_view.rowGroup) == "table") then -- tab_view must be a table
		tab_view.t = tab_view.t .. viewers.ta("add_Row-#rowGroup: ", lua_table.level_count(tab_view.rowGroup) ) -- track to debug
		tab_view.t = tab_view.t .. viewers.ta("add_Row-#case: ", lua_table.level_count(case) ) -- track to debug
		table.insert( tab_view.rowGroup, case)
	elseif (type(case) == "table") and (type(tab_view) == "table") then
	--	tab_view.rowGroup = {}
		table.insert( tab_view.rowGroup, case)
		tab_view.t = (tab_view.t or "") .. viewers.ta("add_Row-#rowGroup: ", lua_table.level_count(tab_view.rowGroup) ) -- track to debug
		tab_view.t = tab_view.t .. viewers.ta("add_Row-#case: ", lua_table.level_count(case) ) -- track to debug
	end
end -- function tableview.add_Row(tab_view)

function tableview.form_all_cases(tab_view) -- Default: Convert all tests cases from test_group to rowGroup.
	local memo = viewers.save_configs("tableview.form_all_cases") -- Save global configuration before eventual changes.
	local tab_view = tab_view
	if (type(tab_view) ~= "table") then tab_view = {} end -- tab_view must be a table
	if type(tab_view.test_group) ~= "table" then -- tab_view.test_group must be a table
		tab_view.test_group = {}
	end
	tab_view.rowGroup = tab_view.rowGroup or {}
	tab_view.track = tab_view.track or {} -- Begin tracking of errors and caracteristics of a tab_view case.
	local trk = tab_view.track
	if (type(tab_view) ~= "table") then trk.tab_view = tab_view end -- err tab_view is table ?
	trk.min_in = 999999 ; trk.max_in = 0
	trk.min_out = 999999 ; trk.max_out = 0
	tab_view.t = tab_view.t or ""
	trk.Start_test = tab_view.test_group -- err tab_view.test_group is table ?
	trk.Start_test_N = lua_table.level_count(tab_view.test_group) -- size tab_view.test_group
	trk.Start_row = tab_view.rowGroup -- err tab_view.test_group is table ?
	trk.Start_row_N = lua_table.level_count(tab_view.rowGroup) -- size tab_view.test_group
	tab_view.t = tab_view.t .. viewers.ta("start#test_group", lua_table.level_count(tab_view.test_group) ) -- track to debug
	if type(tab_view.rowGroup) ~= "table" then tab_view.rowGroup = {} end
	tab_view.t = tab_view.t .. viewers.ta("start#rowGroup", lua_table.level_count(tab_view.rowGroup) ) -- track to debug
	for i, case in ipairs(tab_view.test_group) do
	--	tab_view.t = tab_view.t .. viewers.ta("i", i)
		if case.STOP == "STOP" then break end
		trk.i = i
		trk.case_in = case -- for table error ?
		if type(case) ~= "table" then
			case = { case }
		end -- Cases must be tables of values.
		trk.min_in = 99 ; trk.max_in = 0
		trk.min_out = 99 ; trk.max_out = 0
		if lua_table.level_count(case) < trk.min_in then trk.min_in = lua_table.level_count(case) end
		if lua_table.level_count(case) > trk.max_in then trk.max_in = lua_table.level_count(case) end
		if type(tableview.form_one_case) == "function" then -- Convert all tests cases from test_group to rowGroup.
			case = tab_view.form_one_case(case, tab_view) -- Formats one case
		else
			case = case -- if tableView_form_one_case() is not defined, do not Formats the case
		end
		--	Keep all cells: Insert a masked text in all table cells, to not lost following cells.
		if (type(case) == "table") and (type(tab_view.rowGroup) == "table") then -- Do not fail if case is nil or {}.
			local headers_split = mw.text.split(tab_view.headers, ';', true) -- fr wikisource org
			for i, header in ipairs(headers_split) do
				header = mw.text.trim(header)
				case[i] = case[i] or viewers.usual_color("-", "mask") -- "mask", "discreet", "error"
			end
		end
		if type(case) ~= "table" then -- check case_out
			case = { case }
		end
		if lua_table.level_count(case) < trk.min_out then trk.min_out = lua_table.level_count(case) end
		if lua_table.level_count(case) > trk.max_out then trk.min_out = lua_table.level_count(case) end
		tab_view.add_Row(case, tab_view) -- Default: Add a row to rowGroup.
		trk.End_test = tab_view.test_group -- err tab_view.test_group is table ?
		trk.End_test_N = lua_table.level_count(tab_view.test_group) -- err tab_view.test_group is table ?
		trk.End_row = tab_view.rowGroup -- err tab_view.test_group is table ?
		trk.End_row_N = lua_table.level_count(tab_view.rowGroup) -- err tab_view.test_group is table ?
		tab_view.t = tab_view.t .. "\n* Start: "
		tab_view.t = tab_view.t .. viewers.form9user("tb=<b>%1</b>, tbN=<b>%2</b>, min=<b>%3</b>, max=<b>%4</b>. ", tostring(trk.Start_test), trk.Start_test_N, trk.min_in, trk.max_in) -- track to debug
		tab_view.t = tab_view.t .. viewers.form9user("i=<b>%1</b>, case_in=<b>%2</b>, case_out=<b>%3</b>, ", tostring(trk.i), type(trk.case_in), type(trk.case_out) )
		trk.Start_test = tab_view.test_group -- err tab_view.test_group is table ?
		trk.Start_test_N = lua_table.level_count(tab_view.test_group) -- size tab_view.test_group
		trk.Start_row = tab_view.rowGroup -- err tab_view.test_group is table ?
		trk.Start_row_N = lua_table.level_count(tab_view.rowGroup) -- err tab_view.test_group is table ?
		tab_view.t = tab_view.t .. " ** End: "
		tab_view.t = tab_view.t .. viewers.form9user("tb=<b>%1</b>, tbN=<b>%2</b>, min=<b>%3</b>, max=<b>%4</b>. ", tostring(trk.End_test), trk.End_test_N, trk.min_out, trk.max_out) -- track to debug
		tab_view.track = trk
	end
	viewers.restore_configs(memo, "tableview.form_all_cases") -- Restore global configurations after eventual changes.
end -- function tableview.form_all_cases(tab_view)

function tableview.adapt_options(tab_view) -- Adapt all options for all uses.
	local memo = viewers.save_configs("tableview.adapt_options") -- Save global configuration before eventual changes.
	if type(tab_view) ~= "table" then tab_view = {} end -- tab_view must be a table
	tab_view.t = (tab_view.t or "")
	tab_view.headers = tab_view.headers or "viewers_tableView_default_headers"
	tab_view.headers = viewers.form9user(tab_view.headers)
	tab_view.form_elem_detail = tab_view.form_elem_detail or "viewers_tab_view_form_elem_detail" -- "detail = %1 | %2 | %3 | %4 | %5."
	tab_view.headers_class = tab_view.headers_class or "wikitable alternative center"
	--	headers_class = "wikitable alternative center sortable",
	-- A triable table start with : {| class="wikitable sortable"
	-- A column become fix and not triable with : ||class="unsortable"|
	tab_view.tableStyle = tab_view.tableStyle or " " -- Style of the whole table view.
	tab_view.test_group = tab_view.test_group or viewers.default_test_group
	tab_view.t = (tab_view.t or "") .. viewers.ta("tableView.tab_view.test_group size: ", lua_table.level_count(tab_view.test_group) ) -- track to debug
	tab_view.form_one_case = tab_view.form_one_case or tableview.form_one_case
	tab_view.form_all_cases = tab_view.form_all_cases or tableview.form_all_cases
	tab_view.add_Row = tab_view.add_Row or tableview.add_Row
	tab_view.ccc = tab_view.ccc or tableview.ccc or {} -- To communicate and compute between cases
	tab_view.rowGroup = tab_view.rowGroup or {} -- Only tab_view can change rowGroup to avoid effect from a tableview on the next
	tab_view.track_on = tab_view.track_on or false
	tab_view.t = tab_view.t .. viewers.ta("#tab_view.rowGroup", lua_table.level_count(tab_view.rowGroup) ) -- track to debug
	viewers.restore_configs(memo, "tableview.adapt_options") -- Restore global configurations after eventual changes.
	return tab_view
end -- function tableview.adapt_options(tab_view)

function tableview.form_whole_view(tab_view) -- Formats whole the tableview.new()
	local memo = viewers.save_configs("tableview.form_all_cases") -- Save global configuration before eventual changes.
	local t, err = "", ""
	if (lua_table.level_count(tab_view.test_group) == 0) then
		err = err .. viewers.ta("#tab_view.test_group", lua_table.level_count(tab_view.test_group) )
	end
	local t = viewers.table_head(tab_view.headers_class or "")
	if (type(tab_view.headers) ~= "string") then
		tab_view.headers = "tab_view; headers; missing"
		err = err .. tab_view.headers
	end
	local head = mw.text.split( viewers.form9user(tab_view.headers), ";")
	for i, header in ipairs(head) do -- Formats headers of the table.
		t = t .. viewers.table_col(header or "")
	end
	tableview.form_all_cases(tab_view) -- Default: Convert all tests cases from test_group to rowGroup.
	if (type(tab_view.rowGroup) ~= "table") then tab_view.rowGroup = {} end
	if (lua_table.level_count(tab_view.rowGroup == 0) ) then
		err = err .. "whole:"
		err = err .. viewers.ta("#tab_view.test_group", lua_table.level_count(tab_view.test_group) )
		err = err .. viewers.ta("#tab_view.rowGroup", lua_table.level_count(tab_view.rowGroup) )
	end
	for row_i, columns_i in ipairs(tab_view.rowGroup) do -- Formats the content of each of rows.
		t = t .. viewers.table_row()
		for col, val in ipairs(columns_i) do
			t = t .. viewers.table_dat(val or "") -- each value in columns of row_i
		end
	end
	t = t .. viewers.table_end()
	if tab_view.track_on then t = t .. "tableView_form_whole_view: " .. tostring(err) end
	if (err ~= "") and (tab_view.track_on) then t = t .. "tableView_form_whole_view: " .. tostring(err) end
	viewers.restore_configs(memo, "tableview.form_whole_view")
	return t
end -- function tableview.form_whole_view(tab_view) -- S170610csc

function tableview.new(tab_view) -- Formats a table with lines and columns. S170610tvf
	local memo = viewers.save_configs("tableview.form_whole_view") -- Save global configuration before eventual changes.
	if type(tab_view) ~= "table" then tab_view = {} end -- tab_view must be a table
	tab_view.t = (tab_view.t or "") .. viewers.ta("tableView: ", "start")
	local t = ""
	local err = nil
	tab_view = tableview.adapt_options(tab_view) -- Adapt all options for all uses, before all other adaptations.
	if tab_view.track_on then t = t .. viewers.ta("#test_group", lua_table.level_count(tab_view.test_group) ) .. viewers.ta("#rowGroup", lua_table.level_count(tab_view.rowGroup) ) end
	t = t .. tableview.form_whole_view(tab_view) -- Formats whole the tableview.new()
	if tab_view.track_on then t = t .. viewers.ta("#test_group", lua_table.level_count(tab_view.test_group) ) .. viewers.ta("#rowGroup", lua_table.level_count(tab_view.rowGroup) ) end
	if tab_view.track_on then t = t .. tab_view.t end
	-- Counts of selected and sorted sub-tasks: , #test_group = 43 , #rowGroup = 0
	viewers.restore_configs(memo, "tableview.form_whole_view") -- Restore global configurations after eventual changes.
	return t, err, tab_view
end -- t, err, tab_view = function tableview.new(tab_view)

------------------------------------------------------------------------
------------------------------------------------------------------------

p.ModuleNS = mw.site.namespaces.Module.name .. ":" -- translate Module: in other languages
p.loaded_modules_and_libraries = p.loaded_modules_and_libraries or {}

function p.get_one_module_or_library(title, given_module) -- Get a module or a library, then form and record its descriptor.xx
--	local get, module = p.get_one_module_or_library("Module:Centralizer") -- basic example of use
	local get, module, required, loaded = {}
	if type(title) ~= "string" then
		get.title = "abnormal title : " .. tostring(title)
		get.is_nil = true
		return get
	end -- If not loaded, return only an empty get
	if (type(given_module) == "table") then
		module = given_module
	elseif (type(given_module) == "function") then
		module = given_module()
	else -- to require a new module
		loaded = p.pcallRequire(title) -- require() must not fail and block the page if the module do not exists.
		if (type(loaded) == "table") or (type(loaded) == "function") then module = loaded -- The module is well loaded in package.loaded
		else return get end -- If not loaded, return only get.isTitled and get.title
	end
	get.title = title -- like Module:Author, or the versioning library
	get.module = module -- like {...}
	get.is_nil = not module -- like true or false
	get.is_loaded = true and package.loaded[title] -- true if the module is in package.loaded
	get.is_function = (type(module) == "function") -- true if the module is a function
	get.is_table = (type(module) == "table") -- true if the module is a table
	get.i18n = module.i18n -- i18n table of the module
	get.version = module.version -- table including module.version.known and module.version.sought
	get.is_library = (type(module)=="table") and not (type(module)=="function") and not (string.find(title, p.ModuleNS, 1, true) )
	get.hasi18n = (type(module) == "table") and (type(get.i18n) == "table") -- true if the object has a i18n translations table
	get.versionName = string.gsub(get.title or "", p.ModuleNS, "") -- without Module:		like versioning or Author
	get.versionTitle = p.ModuleNS .. get.versionName -- normalize title					like Module:Author
	get.is_module = string.find(get.title, p.ModuleNS) -- true if the object is				like Module:Author
	get.isI18N = true and string.find(get.title, "/I18N") -- true if the title contains /I18N		like Module:Author/I18N
	get.withoutI18N = string.gsub(get.versionName, "/I18N", "") -- version without /I18N			like versioning or Module:Author
	get.versionI18N = get.withoutI18N .. "/I18N" -- version with /I18N								like Module:Author/I18N
	get.nowstamp = os.date("%Y%m%d%H%M%S") -- like YYYYMMDDhhmmss from module
	-- Special for ISmodule, ISlibrary, ISfunction
	if get.is_library then
		get.revistamp = get.nowstamp
		get.TitleI18N = p.ModuleNS .. "Library/" .. get.withoutI18N .. "/I18N" --	like Module:Library/versioning/I18N
		get.pagename = TitleI18N -- Locate translations										like Module:Library/versioning/I18N
		get.i18nRoot = get.versionName -- Where locate translations are						like versioning
	elseif get.is_module then
		get.revistamp = mw.getCurrentFrame():preprocess( "{{REVISIONTIMESTAMP:" .. get.title .. "}}" )
		get.pagename = "Module:" .. get.versionName -- Locate translations					like Module:Centralizer/I18N
		get.i18nRoot = get.pagename -- Where locate translations are						like Module:Author
		get.TitleI18N = p.ModuleNS .. get.withoutI18N .. "/I18N" --				like Module:Centralizer/I18N
	else
		get.revistamp = mw.getCurrentFrame():preprocess( "{{REVISIONTIMESTAMP:" .. get.title .. "}}" )
	end
	get.versionName = string.gsub(get.title or "", p.ModuleNS, "") -- full version name with perhaps /I18N
	get.simplename = string.gsub(get.versionName, "/I18N", "") -- delete "/I18N" if any
	get.viewI18N = get.simplename
	if type(module) == "function" then
		get.is_function = true -- ISfunction
		get.is_module = false
		get.is_library = false
		get.functionName = get.simplename --												like tostring
		get.pagename = "function:" .. get.simplename --										like function:tostring
	elseif string.find(get.title, p.ModuleNS) then -- If the module title begin with "Module:"
		get.is_function = false
		get.is_module = true -- ISmodule
		get.is_library = false
		get.moduleName = get.title -- complete the title with "Module:"						like Module:Centralizer
		get.subI18N = get.title .. "/I18N" -- eventual sub-module "/I18N"					like Module:Centralizer/I18N
		get.pagename = p.ModuleNS .. get.simplename --								like Module:Centralizer
		if get.isI18N then get.pagename = get.pagename .. "/I18N" end --					like Module:Centralizer/I18N
		if get.isI18N then get.viewI18N = get.simplename .. "/I18N" end --					like Central/I18N
	else -- If the module is a library
		get.is_function = false
		get.is_module = false
		get.is_library = true -- ISlibrary
		get.libraryName = get.title -- standard library name								like versioning
		get.versionName = get.libraryName --												like versioning
		get.pagename = p.ModuleNS .. "Library/" .. get.title --					like Module:Library/versioning
		get.subI18N = get.pagename .. "/I18N" -- /I18N sub-module							like Module:Library/versioning/I18N
		if get.isI18N then get.pagename = get.subI18N end --								like Module:Library/versioning/I18N
		if get.isI18N then get.viewI18N = get.simplename .. "/I18N" end --					like versioning/I18N
	end
	if get.isI18N and (type(get.module) == "table") and (type(get.module.i18n) == "table") then get.sub_i18n = get.module.i18n end
	-- stamp, date and time
	if not get.revistamp then get.revistamp = os.date("%Y%m%d %H%M%S") end
	local function days(stamp) -- approximate the number of days from 0000-01-01
		local day = 0
		if (type(stamp) == "string") and (string.len(stamp) > 7) then
			day = tonumber(string.sub(stamp,1,4)) * 365 +
			tonumber(string.sub(stamp,5,6)) * 30 +
			tonumber(string.sub(stamp,7,8))
		end
		return day
	end
	if get.revistamp then
		get.days_revis = days(get.revistamp)
		get.days_now = days(get.nowstamp)
		get.delay = get.days_now - get.days_revis
		get.revistime = string.sub(get.revistamp,1,4) .. "-" .. string.sub(get.revistamp,5,6) .. "-" .. string.sub(get.revistamp,7,8)
			.. " " .. string.sub(get.revistamp,-6,-5) .. ":" .. string.sub(get.revistamp,-4,-3)
		get.shortdays = string.sub(get.revistamp or "", 3, 8)
		get.shorttime = string.sub(get.revistime or "", -9, -1)
		if get.delay < 25 -- time4
			then get.shortVersion = "v" .. get.shorttime -- short version in "vDD hh:mm" until around 25 days
			else get.shortVersion = "v" .. get.shortdays -- later in date vYYMMDD
		end
		get.versionDate = get.revistime
		get.versionNumber = get.shortVersion
		get.versionName = string.gsub(get.title or "", p.ModuleNS, "") -- full version name with perhaps /I18N
		get.versionDate = get.revistime
		if type(get.module.version) == "table" then -- For central modules or libraries only:
			get.module.versionName = get.versionName -- Record in each module to later IDENTIFY any module. See task T119978, "own module name"
			get.module.versionDate = get.versionDate -- Record in each module to later DATE any module. See task T119978, "own module name"
		end
	end
	if get.version then
		get.sought = get.version.sought or get.version.selector or ""
		get.known = get.version.known or get.version.all_p or ""
		--
		local str = string.gsub(get.sought, " ", ";")
		get.sought_tab = mw.text.split(str, ";", true)
		get.sought_count = lua_table.level_count(get.sought_tab)
		--
		local str = string.gsub(get.known, "*", ";")
		get.known_tab = mw.text.split(str, ";", true)
		get.known_count = lua_table.level_count(get.known_tab)
	end
	-- Record the get descriptor with others
	p.loaded_modules_and_libraries = p.loaded_modules_and_libraries or {}
	if get.i18n then table.insert(p.loaded_modules_and_libraries, get) end
	--
	p.bind_main_and_sub_modules_get = p.bind_main_and_sub_modules_get or {}
	p.bind_main_and_sub_modules_get[get.title] = get
	return get, module
end -- local get, module = p.get_one_module_or_library(title, given_module)

function p.bind_all_sub_modules(sub_modules, iftest) -- Bind all sub-modules of the main module
	local t = t -- t or
	if (type(t) ~= "string") then t = '\n* <b>p.bind_all_sub_modules(sub_modules, iftest)</b> : Bind all sub-modules of the main module' end
	-- Guideline : make a tree a sub modules from the main module
	-- Guideline : for each sub module : try all sought and check its infos from the test by get.isModule ...  like DropBoxCentralTry call the 2 modules DropBox and or CentralTry to diversify tests
	-- F in functions to test groups of : sought, known, sub modules calling 2 simple, missing.
	-- Guideline : submodules with or without : sought, known, sub modules calling 2 simple, missing.
	-- Guideline : test only one complete OK example and one case of each probable error
	local frame = mw.getCurrentFrame() -- this is the frame from Mediawiki
	local main_module_name = frame:getTitle() -- this is the title of the module invoked
	local subtree = {} -- Contains the structure of sub modules, from sought at each branch/level record the result of get_one_module_or_library
	local subsgroup = {} -- Contains the sequence of sub modules for each one record the result of get_one_module_or_library
	local subsgroup = {} -- for each one do not try it if it is already in the tree. But always record it in subtree
	for key, elem in pairs(p.bind_all_sub_modules_test_cases) do -- alternatives = known_tab[i]
		table.insert(subsgroup, { case.insub, case.sub, case.sought, case.known, case.sought, case.known, case.errors or "", } )
	end
	return t, sub_modules.sub_used
end -- t, sub_modules = p.bind_all_sub_modules(sub_modules, iftest) -- Bind all sub-modules of the main module

function p.bind_all_sub_modules_test() -- Test : Bind all sub-modules of the main module.
	p.bind_all_sub_modules_track = "TEST"
	local t = t -- t or
	if (type(t) ~= "string") then t = '\n* <b>p.bind_all_sub_modules_test()</b> : Test : Bind all sub-modules of the main module' end
	local tt, sub_modules = p.bind_all_sub_modules(sub_modules, iftest) -- Bind all sub-modules of the main module
	t = t .. tt
	local subsgroup = {}
	for i, case in pairs(sub_modules) do -- alternatives = known_tab[i]
		table.insert(subsgroup, { case.insub, case.sub, case.sought, case.known, case.sought, case.known, case.errors or "", })
	end -- COCO : in case of minimal tests use the input as results : do do later ...
	local tab_view = { -- Group datas and options for a table view with lines and columns.
		title_memo = "p.bind_all_sub_modules() Test : Bind all sub-modules of the main module",
		test_group = subsgroup,
		form_one_case = function(case) -- Convert a case from test_group to rowGroup.
			return { case.subnane, case.sought, case.known, case.founds, case.missings, case.double, case.errors, }
		end,                                           
		headers = " subnane; sought; known; founds; missings; double; errors ",
		headers_class = "wikitable alternative center sortable",
		rowGroup = {},
	--	track_on == "details", convert function tab_view.form_one_case( to form_one_case = function(
	}
	t = t .. tableview.new(tab_view) -- Runs tests cases and formats a table view with lines and columns.
	return t
end -- t = t .. p.bind_all_sub_modules_test()


------------------------------------------------------------------------
------------------------------------------------------------------------

--p.case
function p.read(frame)
--	p.case = case -- adapted by each main module
--    local mainmodule = mainmodule or p.mainmodule -- adapted by each main module
	local t = "\n* " .. mainmodule .. viewers.ta("subnane", case.subnane) .. viewers.ta("sought", case.sought)
	.. viewers.ta("known", case.known) .. viewers.ta("founds", case.founds) .. viewers.ta("missings", case.missings)
	.. viewers.ta("double", case.double) .. viewers.ta("errors", case.errors or "")
	t = t .. p.bind_all_sub_modules_test()
	return t
end

return p