diff --git a/install/empty_data.php b/install/empty_data.php
index 41b8ba69b46..e576b2082ba 100644
--- a/install/empty_data.php
+++ b/install/empty_data.php
@@ -9158,8 +9158,10 @@ public function getEmptyData(): array
// Test environment data
if ($is_testing) {
$root_entity = array_filter($tables['glpi_entities'], static fn ($e) => $e['id'] === 0);
- $e2e_entity = array_shift($root_entity);
- $e2e_entity = array_replace($e2e_entity, [
+ $root_entity = current($root_entity);
+
+ // Main E2E test entity
+ $e2e_entity = array_replace($root_entity, [
'id' => 1,
'name' => 'E2ETestEntity',
'entities_id' => 0,
@@ -9168,6 +9170,26 @@ public function getEmptyData(): array
]);
$tables['glpi_entities'][] = $e2e_entity;
+ // Sub entity 1
+ $e2e_subentity1 = array_replace($root_entity, [
+ 'id' => 2,
+ 'name' => 'E2ETestSubEntity1',
+ 'entities_id' => 1,
+ 'completename' => __('Root entity') . ' > E2ETestEntity > E2ETestSubEntity1',
+ 'level' => 3,
+ ]);
+ $tables['glpi_entities'][] = $e2e_subentity1;
+
+ // Sub entity 2
+ $e2e_subentity2 = array_replace($root_entity, [
+ 'id' => 3,
+ 'name' => 'E2ETestSubEntity2',
+ 'entities_id' => 1,
+ 'completename' => __('Root entity') . ' > E2ETestEntity > E2ETestSubEntity2',
+ 'level' => 3,
+ ]);
+ $tables['glpi_entities'][] = $e2e_subentity2;
+
// New e2e super-admin user (login: e2e_tests, password: glpi)
$default_glpi_user = array_filter($tables['glpi_users'], static fn ($u) => $u['id'] === self::USER_GLPI);
$e2e_user = array_shift($default_glpi_user);
diff --git a/package-lock.json b/package-lock.json
index 1ecca8de9bc..1c710ed33ff 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,7 +41,7 @@
"jquery": "^3.7.1",
"jquery-migrate": "^3.5.2",
"jquery-prettytextdiff": "^1.0.4",
- "jquery-ui": "^1.13.3",
+ "jquery-ui": "^1.14.0",
"jquery.fancytree": "^2.38.3",
"jquery.rateit": "^1.1.6",
"leaflet": "^1.9.4",
@@ -10746,11 +10746,11 @@
}
},
"node_modules/jquery-ui": {
- "version": "1.13.3",
- "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.3.tgz",
- "integrity": "sha512-D2YJfswSJRh/B8M/zCowDpNFfwsDmtfnMPwjJTyvl+CBqzpYwQ+gFYIbUUlzijy/Qvoy30H1YhoSui4MNYpRwA==",
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.14.0.tgz",
+ "integrity": "sha512-mPfYKBoRCf0MzaT2cyW5i3IuZ7PfTITaasO5OFLAQxrHuI+ZxruPa+4/K1OMNT8oElLWGtIxc9aRbyw20BKr8g==",
"dependencies": {
- "jquery": ">=1.8.0 <4.0.0"
+ "jquery": ">=1.12.0 <5.0.0"
}
},
"node_modules/jquery.fancytree": {
diff --git a/package.json b/package.json
index 83c6b6ad639..9337bd94eeb 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"jquery": "^3.7.1",
"jquery-migrate": "^3.5.2",
"jquery-prettytextdiff": "^1.0.4",
- "jquery-ui": "^1.13.3",
+ "jquery-ui": "^1.14.0",
"jquery.fancytree": "^2.38.3",
"jquery.rateit": "^1.1.6",
"leaflet": "^1.9.4",
diff --git a/phpunit/functional/DbUtilsTest.php b/phpunit/functional/DbUtilsTest.php
index b8142e6ce76..f0221527bb2 100644
--- a/phpunit/functional/DbUtilsTest.php
+++ b/phpunit/functional/DbUtilsTest.php
@@ -574,6 +574,10 @@ public function testGetEntityRestrict()
$this->login();
$instance = new \DbUtils();
+ $root = getItemByTypeName('Entity', '_test_root_entity', true);
+ $child1 = getItemByTypeName('Entity', '_test_child_1', true);
+ $child2 = getItemByTypeName('Entity', '_test_child_2', true);
+
// See all, really all
$_SESSION['glpishowallentities'] = 1; // will be restored by setEntity call
@@ -593,23 +597,23 @@ public function testGetEntityRestrict()
$this->setEntity('_test_root_entity', true);
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('2', '3', '4') ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$root', '$child1', '$child2') ) ",
$instance->getEntitiesRestrictRequest('WHERE', 'glpi_computers')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_computers')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE `glpi_computers`.`entities_id` IN (\'2\', \'3\', \'4\')',
+ "SELECT * FROM `glpi_computers` WHERE `glpi_computers`.`entities_id` IN ('$root', '$child1', '$child2')",
$it->getSql()
);
//keep testing old method from db.function
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('2', '3', '4') ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$root', '$child1', '$child2') ) ",
getEntitiesRestrictRequest('WHERE', 'glpi_computers')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => getEntitiesRestrictCriteria('glpi_computers')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN (\'2\', \'3\', \'4\'))',
+ "SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN ('$root', '$child1', '$child2'))",
$it->getSql()
);
@@ -617,23 +621,23 @@ public function testGetEntityRestrict()
$this->setEntity('_test_root_entity', false);
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('2') ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$root') ) ",
$instance->getEntitiesRestrictRequest('WHERE', 'glpi_computers')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_computers')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE `glpi_computers`.`entities_id` IN (\'2\')',
+ "SELECT * FROM `glpi_computers` WHERE `glpi_computers`.`entities_id` IN ('$root')",
$it->getSql()
);
//keep testing old method from db.function
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('2') ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$root') ) ",
getEntitiesRestrictRequest('WHERE', 'glpi_computers')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => getEntitiesRestrictCriteria('glpi_computers')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN (\'2\'))',
+ "SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN ('$root'))",
$it->getSql()
);
@@ -641,45 +645,45 @@ public function testGetEntityRestrict()
$this->setEntity('_test_child_1', false);
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('3') ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$child1') ) ",
$instance->getEntitiesRestrictRequest('WHERE', 'glpi_computers')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_computers')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE `glpi_computers`.`entities_id` IN (\'3\')',
+ "SELECT * FROM `glpi_computers` WHERE `glpi_computers`.`entities_id` IN ('$child1')",
$it->getSql()
);
//keep testing old method from db.function
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('3') ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$child1') ) ",
getEntitiesRestrictRequest('WHERE', 'glpi_computers')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => getEntitiesRestrictCriteria('glpi_computers')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN (\'3\'))',
+ "SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN ('$child1'))",
$it->getSql()
);
// Child without table
$this->assertSame(
- "WHERE ( `entities_id` IN ('3') ) ",
+ "WHERE ( `entities_id` IN ('$child1') ) ",
$instance->getEntitiesRestrictRequest('WHERE')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => $instance->getEntitiesRestrictCriteria()]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE `entities_id` IN (\'3\')',
+ "SELECT * FROM `glpi_computers` WHERE `entities_id` IN ('$child1')",
$it->getSql()
);
//keep testing old method from db.function
$this->assertSame(
- "WHERE ( `entities_id` IN ('3') ) ",
+ "WHERE ( `entities_id` IN ('$child1') ) ",
getEntitiesRestrictRequest('WHERE')
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => getEntitiesRestrictCriteria()]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE (`entities_id` IN (\'3\'))',
+ "SELECT * FROM `glpi_computers` WHERE (`entities_id` IN ('$child1'))",
$it->getSql()
);
@@ -687,68 +691,68 @@ public function testGetEntityRestrict()
$this->setEntity('_test_child_2', false);
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('4') OR (`glpi_computers`.`is_recursive`='1' AND `glpi_computers`.`entities_id` IN (0, 2)) ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$child2') OR (`glpi_computers`.`is_recursive`='1' AND `glpi_computers`.`entities_id` IN (0, $root)) ) ",
$instance->getEntitiesRestrictRequest('WHERE', 'glpi_computers', '', '', true)
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_computers', '', '', true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN (\'4\') OR (`glpi_computers`.`is_recursive` = \'1\' AND `glpi_computers`.`entities_id` IN (\'0\', \'2\')))',
+ "SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN ('$child2') OR (`glpi_computers`.`is_recursive` = '1' AND `glpi_computers`.`entities_id` IN ('0', '$root')))",
$it->getSql()
);
//keep testing old method from db.function
$this->assertSame(
- "WHERE ( `glpi_computers`.`entities_id` IN ('4') OR (`glpi_computers`.`is_recursive`='1' AND `glpi_computers`.`entities_id` IN (0, 2)) ) ",
+ "WHERE ( `glpi_computers`.`entities_id` IN ('$child2') OR (`glpi_computers`.`is_recursive`='1' AND `glpi_computers`.`entities_id` IN (0, $root)) ) ",
getEntitiesRestrictRequest('WHERE', 'glpi_computers', '', '', true)
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => getEntitiesRestrictCriteria('glpi_computers', '', '', true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE ((`glpi_computers`.`entities_id` IN (\'4\') OR (`glpi_computers`.`is_recursive` = \'1\' AND `glpi_computers`.`entities_id` IN (\'0\', \'2\'))))',
+ "SELECT * FROM `glpi_computers` WHERE ((`glpi_computers`.`entities_id` IN ('$child2') OR (`glpi_computers`.`is_recursive` = '1' AND `glpi_computers`.`entities_id` IN ('0', '$root'))))",
$it->getSql()
);
//Child + parent on glpi_entities
$it->execute(['FROM' => 'glpi_entities', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_entities', '', '', true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_entities` WHERE (`glpi_entities`.`id` IN (\'4\', \'0\', \'2\'))',
+ "SELECT * FROM `glpi_entities` WHERE (`glpi_entities`.`id` IN ('$child2', '0', '$root'))",
$it->getSql()
);
//keep testing old method from db.function
$it->execute(['FROM' => 'glpi_entities', 'WHERE' => getEntitiesRestrictCriteria('glpi_entities', '', '', true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_entities` WHERE ((`glpi_entities`.`id` IN (\'4\', \'0\', \'2\')))',
+ "SELECT * FROM `glpi_entities` WHERE ((`glpi_entities`.`id` IN ('$child2', '0', '$root')))",
$it->getSql()
);
//Child + parent -- automatic recusrivity detection
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_computers', '', '', 'auto')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN (\'4\') OR (`glpi_computers`.`is_recursive` = \'1\' AND `glpi_computers`.`entities_id` IN (\'0\', \'2\')))',
+ "SELECT * FROM `glpi_computers` WHERE (`glpi_computers`.`entities_id` IN ('$child2') OR (`glpi_computers`.`is_recursive` = '1' AND `glpi_computers`.`entities_id` IN ('0', '$root')))",
$it->getSql()
);
//keep testing old method from db.function
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => getEntitiesRestrictCriteria('glpi_computers', '', '', 'auto')]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE ((`glpi_computers`.`entities_id` IN (\'4\') OR (`glpi_computers`.`is_recursive` = \'1\' AND `glpi_computers`.`entities_id` IN (\'0\', \'2\'))))',
+ "SELECT * FROM `glpi_computers` WHERE ((`glpi_computers`.`entities_id` IN ('$child2') OR (`glpi_computers`.`is_recursive` = '1' AND `glpi_computers`.`entities_id` IN ('0', '$root'))))",
$it->getSql()
);
// Child + parent without table
$this->assertSame(
- "WHERE ( `entities_id` IN ('4') OR (`is_recursive`='1' AND `entities_id` IN (0, 2)) ) ",
+ "WHERE ( `entities_id` IN ('$child2') OR (`is_recursive`='1' AND `entities_id` IN (0, $root)) ) ",
$instance->getEntitiesRestrictRequest('WHERE', '', '', '', true)
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => $instance->getEntitiesRestrictCriteria('', '', '', true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE (`entities_id` IN (\'4\') OR (`is_recursive` = \'1\' AND `entities_id` IN (\'0\', \'2\')))',
+ "SELECT * FROM `glpi_computers` WHERE (`entities_id` IN ('$child2') OR (`is_recursive` = '1' AND `entities_id` IN ('0', '$root')))",
$it->getSql()
);
- $it->execute(['FROM' => 'glpi_entities', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_entities', '', 3, true)]);
+ $it->execute(['FROM' => 'glpi_entities', 'WHERE' => $instance->getEntitiesRestrictCriteria('glpi_entities', '', $child1, true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_entities` WHERE (`glpi_entities`.`id` IN (\'3\', \'0\', \'2\'))',
+ "SELECT * FROM `glpi_entities` WHERE (`glpi_entities`.`id` IN ('$child1', '0', '$root'))",
$it->getSql()
);
@@ -760,18 +764,18 @@ public function testGetEntityRestrict()
//keep testing old method from db.function
$this->assertSame(
- "WHERE ( `entities_id` IN ('4') OR (`is_recursive`='1' AND `entities_id` IN (0, 2)) ) ",
+ "WHERE ( `entities_id` IN ('$child2') OR (`is_recursive`='1' AND `entities_id` IN (0, $root)) ) ",
getEntitiesRestrictRequest('WHERE', '', '', '', true)
);
$it->execute(['FROM' => 'glpi_computers', 'WHERE' => getEntitiesRestrictCriteria('', '', '', true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_computers` WHERE ((`entities_id` IN (\'4\') OR (`is_recursive` = \'1\' AND `entities_id` IN (\'0\', \'2\'))))',
+ "SELECT * FROM `glpi_computers` WHERE ((`entities_id` IN ('$child2') OR (`is_recursive` = '1' AND `entities_id` IN ('0', '$root'))))",
$it->getSql()
);
- $it->execute(['FROM' => 'glpi_entities', 'WHERE' => getEntitiesRestrictCriteria('glpi_entities', '', 3, true)]);
+ $it->execute(['FROM' => 'glpi_entities', 'WHERE' => getEntitiesRestrictCriteria('glpi_entities', '', $child1, true)]);
$this->assertSame(
- 'SELECT * FROM `glpi_entities` WHERE ((`glpi_entities`.`id` IN (\'3\', \'0\', \'2\')))',
+ "SELECT * FROM `glpi_entities` WHERE ((`glpi_entities`.`id` IN ('$child1', '0', '$root')))",
$it->getSql()
);
@@ -823,7 +827,7 @@ private function runGetAncestorsOf($cache = false, $hit = false)
}
//test on ent1
- $expected = [0 => 0, 2 => $ent0];
+ $expected = [0 => 0, $ent0 => $ent0];
if ($cache === true && $hit === false) {
$this->assertFalse($GLPI_CACHE->has($ckey_ent1));
} else if ($cache === true && $hit === true) {
@@ -838,7 +842,7 @@ private function runGetAncestorsOf($cache = false, $hit = false)
}
//test on ent2
- $expected = [0 => 0, 2 => $ent0];
+ $expected = [0 => 0, $ent0 => $ent0];
if ($cache === true && $hit === false) {
$this->assertFalse($GLPI_CACHE->has($ckey_ent2));
} else if ($cache === true && $hit === true) {
@@ -1432,6 +1436,8 @@ public function testGetDateCriteriaError2()
public static function autoNameProvider()
{
+ $test_child_1 = getItemByTypeName('Entity', '_test_child_1', true);
+
return [
//will return name without changes
[
@@ -1464,7 +1470,7 @@ public static function autoNameProvider()
'field' => 'name',
'is_template' => true,
'itemtype' => 'Computer',
- 'entities_id' => 3,
+ 'entities_id' => $test_child_1,
'expected' => '_test_pc14'
], [
// not existing on entity, not sanitized, and containing a special char
@@ -1472,7 +1478,7 @@ public static function autoNameProvider()
'field' => 'name',
'is_template' => true,
'itemtype' => 'Computer',
- 'entities_id' => 3,
+ 'entities_id' => $test_child_1,
'expected' => 'pc_>_01'
],
];
diff --git a/phpunit/functional/EntityTest.php b/phpunit/functional/EntityTest.php
index e216fcd3899..d77f37221a9 100644
--- a/phpunit/functional/EntityTest.php
+++ b/phpunit/functional/EntityTest.php
@@ -249,7 +249,7 @@ private function checkParentsSonsAreReset()
$ent1 = getItemByTypeName('Entity', '_test_child_1', true);
$ent2 = getItemByTypeName('Entity', '_test_child_2', true);
- $expected = [0 => 0, 2 => $ent0];
+ $expected = [0 => 0, $ent0 => $ent0];
$ancestors = getAncestorsOf('glpi_entities', $ent1);
$this->assertSame($expected, $ancestors);
@@ -1204,6 +1204,8 @@ public function testRename()
public static function entityTreeProvider(): iterable
{
$e2e_test_root = getItemByTypeName('Entity', 'E2ETestEntity', true);
+ $e2e_test_child1 = getItemByTypeName('Entity', 'E2ETestSubEntity1', true);
+ $e2e_test_child2 = getItemByTypeName('Entity', 'E2ETestSubEntity2', true);
$entity_test_root = getItemByTypeName('Entity', '_test_root_entity');
$entity_test_child_1 = getItemByTypeName('Entity', '_test_child_1');
$entity_test_child_2 = getItemByTypeName('Entity', '_test_child_2');
@@ -1216,7 +1218,16 @@ public static function entityTreeProvider(): iterable
'tree' => [
$e2e_test_root => [
'name' => 'E2ETestEntity',
- 'tree' => []
+ 'tree' => [
+ $e2e_test_child1 => [
+ 'name' => 'E2ETestSubEntity1',
+ 'tree' => [],
+ ],
+ $e2e_test_child2 => [
+ 'name' => 'E2ETestSubEntity2',
+ 'tree' => [],
+ ],
+ ],
],
$entity_test_root->getID() => [
'name' => $entity_test_root->fields['name'],
diff --git a/phpunit/functional/ReminderTest.php b/phpunit/functional/ReminderTest.php
index 586445e2278..874c006c86d 100644
--- a/phpunit/functional/ReminderTest.php
+++ b/phpunit/functional/ReminderTest.php
@@ -43,6 +43,15 @@ class ReminderTest extends DbTestCase
{
public function testAddVisibilityRestrict()
{
+ $e2e_root = getItemByTypeName('Entity', 'E2ETestEntity', true);
+ $e2e_test_child1 = getItemByTypeName('Entity', 'E2ETestSubEntity1', true);
+ $e2e_test_child2 = getItemByTypeName('Entity', 'E2ETestSubEntity2', true);
+ $test_root = getItemByTypeName('Entity', '_test_root_entity', true);
+ $test_child_1 = getItemByTypeName('Entity', '_test_child_1', true);
+ $test_child_2 = getItemByTypeName('Entity', '_test_child_2', true);
+
+ $all_entities = "'0', '$test_root', '$e2e_root', '$e2e_test_child1', '$e2e_test_child2', '$test_child_1', '$test_child_2'";
+
//first, as a super-admin
$this->login();
$users_id = \Session::getLoginUserID();
@@ -50,10 +59,10 @@ public function testAddVisibilityRestrict()
OR `glpi_reminders_users`.`users_id` = '$users_id'
OR (`glpi_profiles_reminders`.`profiles_id` = '4'
AND (`glpi_profiles_reminders`.`no_entity_restriction` = '1'
- OR ((`glpi_profiles_reminders`.`entities_id` IN ('2', '3', '4')
+ OR ((`glpi_profiles_reminders`.`entities_id` IN ('$test_root', '$test_child_1', '$test_child_2')
OR (`glpi_profiles_reminders`.`is_recursive` = '1'
AND `glpi_profiles_reminders`.`entities_id` IN ('0'))))))
- OR ((`glpi_entities_reminders`.`entities_id` IN ('2', '3', '4')
+ OR ((`glpi_entities_reminders`.`entities_id` IN ('$test_root', '$test_child_1', '$test_child_2')
OR (`glpi_entities_reminders`.`is_recursive` = '1'
AND `glpi_entities_reminders`.`entities_id` IN ('0')))))");
$this->assertSame(
@@ -66,8 +75,8 @@ public function testAddVisibilityRestrict()
OR `glpi_reminders_users`.`users_id` = '5'
OR (`glpi_profiles_reminders`.`profiles_id` = '2'
AND (`glpi_profiles_reminders`.`no_entity_restriction` = '1'
- OR (`glpi_profiles_reminders`.`entities_id` IN ('0', '2', '1', '3', '4'))))
- OR (`glpi_entities_reminders`.`entities_id` IN ('0', '2', '1', '3', '4')))");
+ OR (`glpi_profiles_reminders`.`entities_id` IN ($all_entities))))
+ OR (`glpi_entities_reminders`.`entities_id` IN ($all_entities)))");
$this->assertSame(
$expected,
trim(preg_replace('/\s+/', ' ', \Reminder::addVisibilityRestrict()))
@@ -78,8 +87,8 @@ public function testAddVisibilityRestrict()
OR `glpi_reminders_users`.`users_id` = '4'
OR (`glpi_profiles_reminders`.`profiles_id` = '6'
AND (`glpi_profiles_reminders`.`no_entity_restriction` = '1'
- OR (`glpi_profiles_reminders`.`entities_id` IN ('0', '2', '1', '3', '4'))))
- OR (`glpi_entities_reminders`.`entities_id` IN ('0', '2', '1', '3', '4')))");
+ OR (`glpi_profiles_reminders`.`entities_id` IN ($all_entities))))
+ OR (`glpi_entities_reminders`.`entities_id` IN ($all_entities)))");
$this->assertSame(
$expected,
trim(preg_replace('/\s+/', ' ', \Reminder::addVisibilityRestrict()))
@@ -93,11 +102,11 @@ public function testAddVisibilityRestrict()
OR `glpi_reminders_users`.`users_id` = '4'
OR (`glpi_groups_reminders`.`groups_id` IN ('42', '1337')
AND (`glpi_groups_reminders`.`no_entity_restriction` = '1'
- OR (`glpi_groups_reminders`.`entities_id` IN ('0', '2', '1', '3', '4'))))
+ OR (`glpi_groups_reminders`.`entities_id` IN ($all_entities))))
OR (`glpi_profiles_reminders`.`profiles_id` = '6'
AND (`glpi_profiles_reminders`.`no_entity_restriction` = '1'
- OR (`glpi_profiles_reminders`.`entities_id` IN ('0', '2', '1', '3', '4'))))
- OR (`glpi_entities_reminders`.`entities_id` IN ('0', '2', '1', '3', '4')))");
+ OR (`glpi_profiles_reminders`.`entities_id` IN ($all_entities))))
+ OR (`glpi_entities_reminders`.`entities_id` IN ($all_entities)))");
$this->assertSame(
$expected,
trim(preg_replace('/\s+/', ' ', $str))
diff --git a/phpunit/functional/SavedSearchTest.php b/phpunit/functional/SavedSearchTest.php
index 9175fa0decd..2bb49fb48d9 100644
--- a/phpunit/functional/SavedSearchTest.php
+++ b/phpunit/functional/SavedSearchTest.php
@@ -59,6 +59,10 @@ public function testGetVisibilityCriteria()
public function testAddVisibilityRestrict()
{
+ $test_root = getItemByTypeName('Entity', '_test_root_entity', true);
+ $test_child_1 = getItemByTypeName('Entity', '_test_child_1', true);
+ $test_child_2 = getItemByTypeName('Entity', '_test_child_2', true);
+
//first, as a super-admin
$this->login();
$this->assertSame('', \SavedSearch::addVisibilityRestrict());
@@ -91,7 +95,7 @@ public function testAddVisibilityRestrict()
// Check entity restriction
$this->setEntity('_test_root_entity', true);
$this->assertSame(
- "((`glpi_savedsearches`.`is_private` = '1' AND `glpi_savedsearches`.`users_id` = '5') OR (`glpi_savedsearches`.`is_private` = '0')) AND ((`glpi_savedsearches`.`entities_id` IN ('2', '3', '4') OR (`glpi_savedsearches`.`is_recursive` = '1' AND `glpi_savedsearches`.`entities_id` IN ('0'))))",
+ "((`glpi_savedsearches`.`is_private` = '1' AND `glpi_savedsearches`.`users_id` = '5') OR (`glpi_savedsearches`.`is_private` = '0')) AND ((`glpi_savedsearches`.`entities_id` IN ('$test_root', '$test_child_1', '$test_child_2') OR (`glpi_savedsearches`.`is_recursive` = '1' AND `glpi_savedsearches`.`entities_id` IN ('0'))))",
\SavedSearch::addVisibilityRestrict()
);
}
diff --git a/phpunit/functional/SearchTest.php b/phpunit/functional/SearchTest.php
index d9ed138468b..fc9307251c6 100644
--- a/phpunit/functional/SearchTest.php
+++ b/phpunit/functional/SearchTest.php
@@ -355,6 +355,10 @@ public function testFlagMetaComputerUser()
public function testNestedAndMetaComputer()
{
+ $test_root = getItemByTypeName('Entity', '_test_root_entity', true);
+ $test_child_1 = getItemByTypeName('Entity', '_test_child_1', true);
+ $test_child_2 = getItemByTypeName('Entity', '_test_child_2', true);
+
$search_params = [
'reset' => 'reset',
'is_deleted' => 0,
@@ -451,7 +455,7 @@ public function testNestedAndMetaComputer()
$contains = [
"`glpi_computers`.`is_deleted` = 0",
"AND `glpi_computers`.`is_template` = 0",
- "`glpi_computers`.`entities_id` IN ('2', '3', '4')",
+ "`glpi_computers`.`entities_id` IN ('$test_root', '$test_child_1', '$test_child_2')",
"OR (`glpi_computers`.`is_recursive`='1' AND `glpi_computers`.`entities_id` IN (0))",
"`glpi_computers`.`name` LIKE '%test%'",
"AND `glpi_softwares`.`id` = '10784'",
@@ -471,6 +475,10 @@ public function testNestedAndMetaComputer()
public function testViewCriterion()
{
+ $test_root = getItemByTypeName('Entity', '_test_root_entity', true);
+ $test_child_1 = getItemByTypeName('Entity', '_test_child_1', true);
+ $test_child_2 = getItemByTypeName('Entity', '_test_child_2', true);
+
$data = $this->doSearch('Computer', [
'reset' => 'reset',
'is_deleted' => 0,
@@ -491,7 +499,7 @@ public function testViewCriterion()
$contains = [
"`glpi_computers`.`is_deleted` = 0",
"AND `glpi_computers`.`is_template` = 0",
- "`glpi_computers`.`entities_id` IN ('2', '3', '4')",
+ "`glpi_computers`.`entities_id` IN ('$test_root', '$test_child_1', '$test_child_2')",
"OR (`glpi_computers`.`is_recursive`='1' AND `glpi_computers`.`entities_id` IN (0))"
];
@@ -2528,6 +2536,10 @@ public function testSearchWithMultipleFkeysOnSameTable()
public function testSearchAllAssets()
{
+ $test_root = getItemByTypeName('Entity', '_test_root_entity', true);
+ $test_child_1 = getItemByTypeName('Entity', '_test_child_1', true);
+ $test_child_2 = getItemByTypeName('Entity', '_test_child_2', true);
+
$data = $this->doSearch('AllAssets', [
'reset' => 'reset',
'is_deleted' => 0,
@@ -2571,7 +2583,7 @@ public function testSearchAllAssets()
$data['sql']['search']
);
$this->assertStringContainsString(
- "`$type`.`entities_id` IN ('2', '3', '4')",
+ "`$type`.`entities_id` IN ('$test_root', '$test_child_1', '$test_child_2')",
$data['sql']['search']
);
$this->assertStringContainsString(
diff --git a/templates/layout/parts/profile_selector.html.twig b/templates/layout/parts/profile_selector.html.twig
index a56e7e45c46..2f8e12bbf4b 100644
--- a/templates/layout/parts/profile_selector.html.twig
+++ b/templates/layout/parts/profile_selector.html.twig
@@ -102,7 +102,7 @@
title="{{ __("Clear search") }}" data-bs-toggle="tooltip" data-bs-placement="top">
-
@@ -256,9 +256,9 @@
hotkeys('ctrl+alt+e, option+command+e', async function(e) {
e.stopPropagation();
e.preventDefault();
- $('.user-menu-dropdown-toggle').dropdown('show');
+ $('.user-menu-dropdown-toggle:visible').dropdown('show');
await new Promise(r => setTimeout(r, 100));
- $('.entity-dropdown-toggle').dropdown('show');
+ $('.user-menu-dropdown-toggle:visible').parent().find('.entity-dropdown-toggle').dropdown('show');
$('input[name=entsearchtext]').filter(":visible")[0].focus();
});
});
diff --git a/tests/cypress/e2e/entities_selector.cy.js b/tests/cypress/e2e/entities_selector.cy.js
new file mode 100644
index 00000000000..0ada7e8ad9d
--- /dev/null
+++ b/tests/cypress/e2e/entities_selector.cy.js
@@ -0,0 +1,104 @@
+/**
+ * ---------------------------------------------------------------------
+ *
+ * GLPI - Gestionnaire Libre de Parc Informatique
+ *
+ * http://glpi-project.org
+ *
+ * @copyright 2015-2024 Teclib' and contributors.
+ * @copyright 2003-2014 by the INDEPNET Development Team.
+ * @licence https://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * ---------------------------------------------------------------------
+ *
+ * LICENSE
+ *
+ * This file is part of GLPI.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * ---------------------------------------------------------------------
+ */
+describe('Entities selector', () => {
+ beforeEach(() => {
+ cy.login();
+ cy.changeProfile('Super-Admin', true);
+
+ // Go to any page; force the entity to be E2ETestEntity
+ cy.visit('/front/central.php?active_entity=1');
+ cy.get('header').findByTitle('Root entity > E2ETestEntity').should('exist');
+ });
+
+ after(() => {
+ cy.visit('/front/central.php?active_entity=1&is_recursive=1');
+ });
+
+ it('Can switch to full structure', () => {
+ cy.openEntitySelector();
+
+ // Enable full structure
+ cy.get('header').findByTitle('Root entity > E2ETestEntity (full structure)').should('not.exist');
+ cy.findByRole("button", {'name': "Select all"}).click();
+ cy.get('header').findByTitle('Root entity > E2ETestEntity (full structure)').should('exist');
+ });
+
+ it('Can search for entities', () => {
+ cy.openEntitySelector();
+
+ // Search for a specific entity
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity1"}).should('not.exist');
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity2"}).should('not.exist');
+ cy.focused().type("Entity2");
+ cy.findByRole("button", {'name': "Search"}).click();
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity1"}).should('not.exist');
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity2"}).should('exist');
+
+ // Go to entity 2
+ cy.get('header').findByTitle('Root entity > E2ETestEntity > E2ETestSubEntity2').should('not.exist');
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity2"})
+ .findByRole('link', {'name': "E2ETestSubEntity2"})
+ .as("entity_link")
+ .click()
+ ;
+ cy.get('@entity_link').click(); // Not sure why but the link only work in cypress if you click twice...
+ cy.get('header').findByTitle('Root entity > E2ETestEntity > E2ETestSubEntity2').should('exist');
+ });
+
+ it('Can fold/unfold tree', () => {
+ cy.openEntitySelector();
+
+ // Unfold the tree
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity1"}).should('not.exist');
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity2"}).should('not.exist');
+ cy.get('.fancytree-expander[role=button]:visible').as('toggle_tree').click(); // We don't have access to a more precise selector here, so we have to rely on css
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity1"}).should('exist');
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity2"}).should('exist');
+
+ // Fold tree again
+ cy.get('@toggle_tree').click();
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity1"}).should('not.exist');
+ cy.findByRole('gridcell', {'name': "E2ETestSubEntity2"}).should('not.exist');
+ });
+
+ it('Can enable sub entities', { retries: {runMode: 2, openMode: 0} }, () => {
+ cy.openEntitySelector();
+
+ // Enable sub entities
+ cy.get('header').findByTitle('Root entity > E2ETestEntity (tree structure)').should('not.exist');
+ cy.findByRole('gridcell', {'name': "Root entity > E2ETestEntity+ sub-entities"})
+ .findByLabelText('+ sub-entities')
+ .click();
+ cy.get('header').findByTitle('Root entity > E2ETestEntity (tree structure)').should('exist');
+ });
+});
diff --git a/tests/cypress/e2e/fileupload.cy.js b/tests/cypress/e2e/fileupload.cy.js
new file mode 100644
index 00000000000..6d39be18926
--- /dev/null
+++ b/tests/cypress/e2e/fileupload.cy.js
@@ -0,0 +1,56 @@
+/**
+ * ---------------------------------------------------------------------
+ *
+ * GLPI - Gestionnaire Libre de Parc Informatique
+ *
+ * http://glpi-project.org
+ *
+ * @copyright 2015-2024 Teclib' and contributors.
+ * @copyright 2003-2014 by the INDEPNET Development Team.
+ * @licence https://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * ---------------------------------------------------------------------
+ *
+ * LICENSE
+ *
+ * This file is part of GLPI.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * ---------------------------------------------------------------------
+ */
+describe('File upload', () => {
+ beforeEach(() => {
+ cy.login();
+ cy.changeProfile('Super-Admin', true);
+ cy.visit('/front/document.form.php');
+ });
+
+ it('Can upload file', () => {
+ // Upload file
+ cy.get("input[type=file]").selectFile("fixtures/uploads/bar.txt");
+ cy.findByText('Upload successful').should('exist');
+ cy.findByRole("button", {'name': "Add"}).click();
+ cy.findByRole('textbox', {'name': "Name"}).should('have.value', 'bar.txt');
+
+ // Download file
+ cy.get('#main-form')
+ .findByRole('link', {'name': "bar.txt"})
+ .invoke('attr', 'target', '_self') // Cypress don't like new tabs
+ .click();
+ cy.readFile('cypress/downloads/bar.txt').then(content => {
+ cy.wrap('bar').should('eq', content);
+ });
+ });
+});
diff --git a/tests/cypress/support/commands.d.ts b/tests/cypress/support/commands.d.ts
index 243cfffc687..d2c0f6f804d 100644
--- a/tests/cypress/support/commands.d.ts
+++ b/tests/cypress/support/commands.d.ts
@@ -33,6 +33,7 @@
declare namespace Cypress {
interface Chainable {
+ openEntitySelector(): Chainable
startToDrag(): Chainable
dropDraggedItemAfter(): Chainable
checkAndCloseAlert(text: string): Chainable
diff --git a/tests/cypress/support/commands.js b/tests/cypress/support/commands.js
index 34a1cea898b..f20a30543ab 100644
--- a/tests/cypress/support/commands.js
+++ b/tests/cypress/support/commands.js
@@ -401,6 +401,16 @@ Cypress.Commands.add('disableDebugMode', () => {
});
});
+Cypress.Commands.add('openEntitySelector', () => {
+ cy.intercept('GET', '/ajax/entitytreesons.php*').as('load_data_request');
+
+ cy.findAllByText('Select the desired entity').should('not.be.visible');
+ cy.get('body').type('{ctrl}{alt}e');
+ cy.findAllByText('Select the desired entity').should('be.visible');
+
+ cy.wait('@load_data_request');
+});
+
// The "startToDrag" and "dropDraggedItemAfter" commands are not perfect as they
// simulate dragging by moving the DOM node using jquery.
//