pluginsEnabled[] = 'luxtools';
parent::setUp();
// Setup config so that access to the TMP directory will be allowed
// Use the built-in file.php endpoint.
$conf ['plugin']['luxtools']['paths'] = TMP_DIR . '/filelistdata/' . "\n" . 'A> /Scape';
}
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
// copy test files to test directory
\TestUtils::rcopy(TMP_DIR, dirname(__FILE__) . '/filelistdata');
}
/**
* Run a list of checks on the given document
*
* @param Document $doc
* @param array $structure Array of selectors and expected count or content
* @return void
*/
protected function structureCheck(Document $doc, $structure)
{
foreach ($structure as $selector => $expected) {
if (is_numeric($expected)) {
$this->assertEquals(
$expected,
$doc->find($selector)->count(),
'Selector ' . $selector . ' not found'
);
} else {
$this->assertStringContainsString(
$expected,
$doc->find($selector)->text(),
'Selector ' . $selector . ' not found'
);
};
}
}
/**
* This function checks that all files are listed in not recursive mode.
* Uses {{files>...}} syntax for backwards compatibility (now handled by directory syntax).
*/
public function test_not_recursive()
{
global $conf;
// Render filelist using files syntax (now handled by directory plugin)
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&direct=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
// We should find:
// - example.txt
// - exampleimage.png
$result = strpos($xhtml, 'example.txt');
$this->assertFalse($result === false, '"example.txt" not listed');
$result = strpos($xhtml, 'exampleimage.png');
$this->assertFalse($result === false, '"exampleimage.png" not listed');
}
/**
* This function checks that all files are listed in recursive mode.
* Uses {{files>...}} syntax for backwards compatibility (now handled by directory syntax).
*/
public function test_recursive()
{
// Render filelist using files syntax (now handled by directory plugin)
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&direct=1&recursive=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
// We should find:
// - exampledir
// - example2.txt
// - example.txt
// - exampleimage.png
$result = strpos($xhtml, 'exampledir');
$this->assertFalse($result === false, '"exampledir" not listed');
$result = strpos($xhtml, 'example2.txt');
$this->assertFalse($result === false, '"example2.txt" not listed');
$result = strpos($xhtml, 'example.txt');
$this->assertFalse($result === false, '"example.txt" not listed');
$result = strpos($xhtml, 'exampleimage.png');
$this->assertFalse($result === false, '"exampleimage.png" not listed');
}
/**
* This function checks the rendering when style=list is explicitly specified.
* Note: The files syntax is now handled by directory syntax and always renders as table.
* This test is kept for backwards compatibility testing but expects table structure.
*/
public function testUnorderedList()
{
// Render filelist with explicit style=list (now ignored, renders as table)
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&style=list&direct=1&recursive=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
// Now renders as a table instead of list
$structure = [
'div.luxtools-plugin' => 1,
'div.luxtools-plugin table' => 1,
];
$this->structureCheck($doc, $structure);
}
/**
* This function checks the rendering when style=olist is explicitly specified.
* Note: The files syntax is now handled by directory syntax and always renders as table.
* This test is kept for backwards compatibility testing but expects table structure.
*/
public function testOrderedList()
{
// Render filelist with explicit style=olist (now ignored, renders as table)
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&style=olist&direct=1&recursive=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
// Now renders as a table instead of ordered list
$structure = [
'div.luxtools-plugin' => 1,
'div.luxtools-plugin table' => 1,
];
$this->structureCheck($doc, $structure);
}
/**
* This function checks that the table mode
* generates the expected XHTML structure.
*/
public function test_table()
{
global $conf;
// Render filelist
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&style=table&direct=1&recursive=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$structure = [
'div.luxtools-plugin' => 1,
'div.luxtools-plugin table' => 1,
'div.luxtools-plugin table > tbody > tr' => 3,
'div.luxtools-plugin table > tbody > tr:nth-child(1) a' => 'example.txt',
'div.luxtools-plugin table > tbody > tr:nth-child(2) a' => 'exampledir/example2.txt',
'div.luxtools-plugin table > tbody > tr:nth-child(3) a' => 'exampleimage.png',
];
$this->structureCheck($doc, $structure);
}
public function test_default_maxheight_applies_scroll()
{
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&style=list&direct=1&recursive=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$style = (string)$doc->find('div.luxtools-plugin')->attr('style');
$this->assertStringContainsString('max-height: 500px', $style);
$this->assertStringContainsString('overflow-y: auto', $style);
}
public function test_maxheight_can_be_disabled()
{
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&style=table&direct=1&recursive=1&maxheight=-1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$style = $doc->find('div.luxtools-plugin')->attr('style');
$this->assertTrue($style === null || $style === '');
}
/**
* This function checks that the images syntax renders a thumbnail gallery.
*/
public function test_images_gallery()
{
$instructions = p_get_instructions('{{images>' . TMP_DIR . '/filelistdata/*&direct=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$structure = [
'div.luxtools-plugin.luxtools-gallery' => 1,
'div.luxtools-plugin.luxtools-gallery a' => 1,
'div.luxtools-plugin.luxtools-gallery img' => 1,
];
$this->structureCheck($doc, $structure);
$this->assertStringContainsString('exampleimage.png', $xhtml);
$this->assertStringContainsString('thumb=1', $xhtml);
$this->assertStringContainsString('width="150"', $xhtml);
$this->assertStringContainsString('height="150"', $xhtml);
}
/**
* Grouping wrapper should use default flex mode with zero gap.
*/
public function test_grouping_default_flex()
{
$imagePath = TMP_DIR . '/filelistdata/exampleimage.png';
$syntax = ''
. '{{image>' . $imagePath . '|One|120}}'
. '{{image>' . $imagePath . '|Two|120}}'
. '';
$instructions = p_get_instructions($syntax);
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$structure = [
'div.luxtools-grouping.luxtools-grouping--flex' => 1,
'div.luxtools-grouping .luxtools-imagebox' => 2,
];
$this->structureCheck($doc, $structure);
$style = (string)$doc->find('div.luxtools-grouping')->first()->attr('style');
$this->assertStringContainsString('--luxtools-grouping-cols: 2', $style);
$this->assertStringContainsString('--luxtools-grouping-gap: 0', $style);
$this->assertStringContainsString('--luxtools-grouping-justify: start', $style);
$this->assertStringContainsString('--luxtools-grouping-align: start', $style);
}
/**
* Grouping wrapper should accept custom flex layout and gap.
*/
public function test_grouping_custom_flex()
{
$imagePath = TMP_DIR . '/filelistdata/exampleimage.png';
$syntax = ''
. '{{image>' . $imagePath . '|One|120}}'
. '{{image>' . $imagePath . '|Two|120}}'
. '';
$instructions = p_get_instructions($syntax);
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$structure = [
'div.luxtools-grouping.luxtools-grouping--flex' => 1,
'div.luxtools-grouping .luxtools-imagebox' => 2,
];
$this->structureCheck($doc, $structure);
$style = (string)$doc->find('div.luxtools-grouping')->first()->attr('style');
$this->assertStringContainsString('--luxtools-grouping-gap: 8px', $style);
}
/**
* Grouping wrapper should accept justify and align controls.
*/
public function test_grouping_justify_and_align()
{
$imagePath = TMP_DIR . '/filelistdata/exampleimage.png';
$syntax = ''
. '{{image>' . $imagePath . '|One|120}}'
. '{{image>' . $imagePath . '|Two|120}}'
. '';
$instructions = p_get_instructions($syntax);
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$style = (string)$doc->find('div.luxtools-grouping')->first()->attr('style');
$this->assertStringContainsString('--luxtools-grouping-justify: space-between', $style);
$this->assertStringContainsString('--luxtools-grouping-align: center', $style);
}
/**
* Unknown grouping attributes should render a warning string.
*/
public function test_grouping_unknown_option_warning()
{
$imagePath = TMP_DIR . '/filelistdata/exampleimage.png';
$syntax = ''
. '{{image>' . $imagePath . '|One|120}}'
. '';
$instructions = p_get_instructions($syntax);
$xhtml = p_render('xhtml', $instructions, $info);
$this->assertStringContainsString('[grouping: unknown option(s): gpa]', $xhtml);
}
/**
* Ensure the built-in file endpoint includes the host page id so file.php can
* enforce per-page ACL.
*/
public function test_file_links_include_page_id_for_acl()
{
global $ID;
$ID = 'luxtools:acltest';
$instructions = p_get_instructions('{{files>' . TMP_DIR . '/filelistdata/*&style=list&direct=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$href = (string)$doc->find('div.luxtools-plugin a')->first()->attr('href');
$this->assertNotSame('', $href);
$this->assertStringContainsString('lib/plugins/luxtools/file.php', $href);
$this->assertStringContainsString('id=luxtools%3Aacltest', $href);
}
/**
* This function checks that the open syntax renders an inline link.
*/
public function test_open_link()
{
$instructions = p_get_instructions('{{open>/tmp/somewhere|Open here}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$structure = [
'a.luxtools-open' => 1,
];
$this->structureCheck($doc, $structure);
$this->assertStringContainsString('Open here', $xhtml);
$this->assertStringContainsString('data-path="/tmp/somewhere"', $xhtml);
}
/**
* This function checks that the directory syntax renders a flat table,
* listing both folders and files.
*/
public function test_directory_table_flat()
{
$instructions = p_get_instructions('{{directory>' . TMP_DIR . '/filelistdata/&direct=1}}');
$xhtml = p_render('xhtml', $instructions, $info);
$doc = new Document();
$doc->html($xhtml);
$structure = [
'div.luxtools-plugin' => 1,
'div.luxtools-plugin table' => 1,
'div.luxtools-plugin table > tbody > tr' => 3,
'a.luxtools-open' => 1,
];
$this->structureCheck($doc, $structure);
// Should list the top-level entries, but not recurse into exampledir
$this->assertStringContainsString('example.txt', $xhtml);
$this->assertStringContainsString('exampleimage.png', $xhtml);
$this->assertStringContainsString('exampledir', $xhtml);
$this->assertStringNotContainsString('example2.txt', $xhtml);
// Directory row should trigger the same behaviour as {{open>...}} for that folder
$this->assertStringContainsString('data-path="/Scape/exampledir"', $xhtml);
}
}