'App\Model\Table\MaterielsTable'
];
$this->Materiels = TableRegistry::get('Materiels', $config);
$config = TableRegistry::exists('Suivis') ? [] : [
'className' => 'App\Model\Table\SuivisTable'
];
$this->Suivis = TableRegistry::get('Suivis', $config);
*/ /*
$this->ControllerApp = new AppController();
}
public function tearDown() {
//unset($this->Materiels);
//unset($this->Suivis);
unset($this->ControllerApp);
parent::tearDown();
}
*/
public function setUp() {
// (EP202010)
// https://stackoverflow.com/questions/29748911/cakephp-connections-while-testing/45592461
/*
* Some tables tests were getting default db instead of test db for no reason.
* This solves the problem (we have a main test class from which we extend all tests, do some setting up. We put it there)
*/
TableRegistry::clear();
parent::setUp();
//$this->toto = 'titi';
// Check qu'on lit bien la table configurations de la BD de test !!
$config = TableRegistry::exists('Configurations') ? [] : [
'className' => 'App\Model\Table\ConfigurationsTable'
];
$confLabinvent = TableRegistry::getTableLocator()->get('Configurations', $config)->find()->first();
//assert($confLabinvent->ldap_authenticationType == 'uid', 'On ne lit pas la bonne configuration');
//debug($confLabinvent->ldap_authenticationType);
$this->assertTextEquals('uid', $confLabinvent->ldap_authenticationType, 'On ne lit pas la bonne configuration');
$this->assertTextNotEquals('samaccountname', $confLabinvent->ldap_authenticationType, 'On ne lit pas la bonne configuration');
$this->assertTextEquals(1, $confLabinvent->test, 'On ne lit pas la bonne configuration');
$this->assertTextEquals(800, $confLabinvent->prix_inventaire_administratif, 'On ne lit pas la bonne configuration');
$this->assertTextEquals('TEST', $confLabinvent->labNameShort, 'On ne lit pas la bonne configuration');
// On lit la config de test pour les champs materiels
/*
#Configure::config('my_yaml_engine', new YamlConfig());
$filetoload = CORE_PATH . 'config' . DS . CONFIG_MATERIEL_FIELDS_FILE_NAME.'.test.yml';
Configure::load($filetoload, 'my_yaml_engine');
*/
}
public function d($msg) {
if ($this->DEBUG) pr($msg);
}
/*
* On recupère une entité quelconque de la BD (fixture), peu importe ce que c'est car on va la modifier
* Par défaut, on utilise la première entité de la BD (id 1)
*/
static protected function _getEntityIdOkForTesting() {
return 1;
}
// To be overriden by subclasses
protected function getNewEntityWithAllMandatoryFields() {
throw new NotImplementedException(__METHOD__);
}
protected function getEntitiesName() {
//throw new NotImplementedException("Méthode getEntitiesName() non implémentée !!");
$test_class_name = get_class($this); // MaterielsControllerTest, SurCategoriesControllerTest, ...
//debug($test_class_name);
$entities_name = explode('\\', substr($test_class_name,0,strpos($test_class_name, 'ControllerTest')));
//debug($entities_name);
return $entities_name[count($entities_name)-1];
}
protected function getNbEntitiesInFixture() {
$entities_name = $this->getEntitiesName();
$nb = TableRegistry::getTableLocator()->get($entities_name)->find()->count();
//$this->d("nb entities in fixture: $nb");
return $nb;
}
protected function getNbEntitiesExpectedInIndexView() {
return $this->getNbEntitiesInFixture();
}
protected function getMaterielsTable() {
//if (!$this->Materiels) $this->Materiels = TableRegistry::get('Materiels');
if (!$this->Materiels) $this->Materiels = TableRegistry::getTableLocator()->get('Materiels');
return $this->Materiels;
/*
$m = $this->Materiels->get($id);
return $m;
*/
}
protected function getMaterielsController() {
// On est dans MaterielsControllerTest => on retourne le controleur courant
if ($this->getEntitiesName()=='Materiels') return $this->_getController();
// Sinon, on retourne une instance spécifique pour les materiels
if (!$this->controller_materiels_instance) $this->controller_materiels_instance = new MaterielsController();
return $this->controller_materiels_instance;
}
protected function _getController() {
//if (!$this->controller_instance) $this->controller_instance = new MaterielsController();
$entities_name = $this->getEntitiesName(); // ex: 'Materiels', 'Suivis', 'SurCategories'...
//$entities_name = 'SurCategories';
//debug("entities_name is $entities_name");
$controller_name = $this->_getControllerFullNameFromEntitiesName($entities_name);
//debug("controller_name is $controller_name"); exit;
if (!$this->controller_instance) $this->controller_instance = new $controller_name();
return $this->controller_instance;
}
protected static function _getControllerInstanceFromName($entities_name) {
//$controller_name = $this->_getControllerFullNameFromEntitiesName($entities_name);
$controller_name = self::_getControllerFullNameFromEntitiesName($entities_name);
return new $controller_name();
}
/*
* $entities_name is 'Materiels', 'Suivis', 'SurCategories'...
* @return : App\Controller\SurCategoriesController, ...
*/
private static function _getControllerFullNameFromEntitiesName($entities_name) {
//$entities_name = ucfirst(strtolower($entities_name)); // Materiels, Suivis, Emprunts...
//$entities_name = ucfirst(strtolower($entities_name)); // Materiels, Suivis, Emprunts...
//$controller_name = 'App\\Controller\\'.$this->getEntitiesName().'Controller'; // ex: 'Materiels' ou 'Suivis'...
return 'App\\Controller\\'.$entities_name.'Controller'; // ex: 'MaterielsController' ou 'SuivisController'...
//$controller_name = 'App\\Controller\\'.$this->getEntitiesName().'Controller'; // ex: 'Materiels' ou 'Suivis'...
}
// This are data providers used for a lot of tests
// See https://jtreminio.com/2013/03/unit-testing-tutorial-part-2-assertions-writing-a-useful-test-and-dataprovider
public function dataProviderRoles4() { return $this->ROLES4; }
public function dataProviderRoles5() { return $this->ROLES5; }
// Idem dataProviderRoles5 mais avec USER_from_ldap en plus:
public function dataProviderRoles6() { return $this->ROLES6; }
protected function getActions() {
//return ['toto'];
return $this->_getController()->getActions();
}
// Combinaison de roles (U,R,A,S) et statuts (C,V,T,A)
public function dataProviderRoles4AndStatuses4() {
$roles_and_statuses = [];
foreach ($this->ROLES4 as $user_role) {
//debug($user_role[0]);
foreach ($this->MATOS_STATUSES as $matos_status)
$roles_and_statuses[] = [$user_role[0], $matos_status[0]];
}
//$this->d($roles_and_statuses);
return $roles_and_statuses;
}
//public function dataProviderActionsAndRoles4($controller) {
public function dataProviderActionsAndRoles4() {
$actions_and_roles = [];
$actions = $this->getActions();
//$actions = ['add'];
//$actions = MaterielsController::getActions();
//$controller = 'App\\Controller\\'.$controller;
//debug($this);
//debug("controller is $controller_name"); exit;
//$actions = $controller_name::getActions();
//$actions = SuivisController::getActions();
//debug($actions); exit;
//debug("entities is : ".$this->getEntitiesName()); exit;
//$actions = $this->getController()->getActions();
//debug("Liste des Actions à tester:");debug($actions); exit;
//foreach ($actions as $a) echo("$a\n");
/*
*/
/*
$actions = [
// CRUD
'add','add_by_copy', 'view','index','edit','delete',
//'view',
//'index',
// Autres
'statusCreated',
];
*/
$roles4 = [
'user',
'resp',
'admin',
'super',
/*
*/
];
//$actions = ['delete'];
//$actions = ['edit'];
foreach ($actions as $action)
//foreach ([0,1] as $i) {
//foreach ([1] as $i) {
//foreach ([0] as $i) {
foreach ([0,1,2,3] as $i) {
$item = [ $action, $roles4[$i], $this->ROLES4[$i][0] ];
//debug($item);
$actions_and_roles[] = $item;
}
return $actions_and_roles;
}
/* FONCTIONS UTILITAIRES UTILISÉES PAR (tous) LES TESTS */
public static function getRoleLevel($role) { return AppController::getRoleLevel($role); }
// Definition DIFFERENTE de celle de AppController
public function getUserRole() {
//return $this->ControllerMateriels->getUserRole();
if (! $this->CURRENT_ROLE) {
$user = $this->getCurrentUser();
/*
$user = TableRegistry::get('Users')->find()->where([
// username = LOGIN (ex: 'epallier') ; pour les tests : user1_SUPER, user5_USER, ...
'username' => $this->_session['Auth']['User']['uid'][0]
//'username' => 'user1_SUPER'
//'username' => $this->_session['Auth']['User']['cn'][0]
])->first();
*/
// Unpriviledged user
$role = $user ? $user['role'] : "Utilisateur";
$this->CURRENT_ROLE = $role;
}
return $this->CURRENT_ROLE;
}
protected function getCurrentUser() {
if (! $this->CURRENT_USER) {
$this->CURRENT_USER = TableRegistry::get('Users')->find()->where([
// username = LOGIN (ex: 'epallier') ; pour les tests : user1_SUPER, user5_USER, ...
'username' => $this->_session['Auth']['User']['uid'][0]
//'username' => 'user1_SUPER'
//'username' => $this->_session['Auth']['User']['cn'][0]
])->first();
}
return $this->CURRENT_USER;
}
// MEME Definition de celle de AppController (mais n'utilise pas la meme fonction getUserRole())
public function userHasRole($expectedRole, $ORMORE=false) {
$role = $this->getUserRole();
//debug($role);
if (! $ORMORE) return ($role == $expectedRole);
return ($this->getRoleLevel($role) >= $this->getRoleLevel($expectedRole));
}
// MEME Definition de celle de AppController (mais n'utilise la meme fonction getUserRole())
public function userHasRoleAtLeast($expectedRole) {
return $this->userHasRole($expectedRole, true);
}
// MEME Definition de celle de AppController (mais n'utilise la meme fonction getUserRole())
public function USER_IS_ADMIN_AT_LEAST() { return $this->userHasRoleAtLeast('Administration'); }
public function USER_IS_RESP_AT_LEAST() { return $this->userHasRoleAtLeast('Responsable'); }
public function USER_IS_SUPERADMIN() { return $this->userHasRole('Super Administrateur'); }
//public function USER_IS_ADMIN_PLUS() { return $this->userHasRole('Administration Plus'); }
public function USER_IS_ADMIN() { return $this->userHasRole('Administration'); }
public function USER_IS_RESP() { return $this->userHasRole('Responsable'); }
public function USER_IS_USER() { return $this->userHasRole('Utilisateur'); }
/*
public function USER_IS_ADMIN_AT_LEAST($role=null) {
if (is_null($role)) {
$role = $this->getUserRole();
$roles = ['Administration','Administration Plus','Super Administrateur'];
}
else {
$roles = ['ADMIN','ADMINP','SUPER'];
}
return in_array($role, $roles);
}
*/
public function authAs($role) {
switch ($role) {
case 'USER_from_ldap':
$this->authUtilisateurFromLdap();
//$this->CURRENT_ROLE = 'Utilisateur';
break;
case 'USER':
$this->authUtilisateurFromTable();
//$this->CURRENT_ROLE = 'Utilisateur';
break;
case 'RESP':
$this->authResponsable();
//$this->CURRENT_ROLE = 'Responsable';
break;
case 'ADMIN':
$this->authAdmin();
//$this->CURRENT_ROLE = 'Administration';
break;
/*
case 'ADMINP':
$this->authAdminPlus();
//$this->CURRENT_ROLE = 'Administration Plus';
break;
*/
case 'SUPER':
$this->authSuperAdmin();
//$this->CURRENT_ROLE = 'Super Administrateur';
break;
}
}
// authUser('login', 'Prenom', 'Nom');
// ex: $this->authUser('u1SUPER', 'user1', 'SUPER');
// ex: $this->authUser('user5_USER', 'test9', 'test0');
private function authUser($login, $givenName='test1', $name='test2') {
$user = [
'Auth' => [
'User' => [
// Nom
'sn' => [
0 => $name
],
// Email (normalement prenom.nom@test.fr)
'mail' => [
0 => 'testa@test.fr'
],
// Prenom
'givenname' => [
0 => $givenName
],
// LOGIN (normalement epallier)
/*
'cn' => [
0 => $cn
],
*/
'uid' => [
0 => $login
],
'userpassword' => [
0 => 'test'
]
]
]
];
$this->session($user);
//$this->request->getSession()->write($user);
$authType = [
'authType' => 'cn'
];
$this->session($authType);
//$this->request->getSession()->write($authType);
(new UsersController())->statsUpdateForCurrentUserWhen($user['Auth']['User'],'login');
}
public function authSuperAdmin() {
//$this->authUser('login', 'Prenom', 'Nom');
$this->authUser('u1SUPER', 'user1', 'SUPER');
///$this->authUser('user1_SUPER', 'user1', 'SUPER');
//$this->authUser('user1_SUPER', 'test1', 'test2');
//$this->authUser('testa', 'user1', 'SUPER');
}
/*
public function authSuperAdmin() {
$user = [
'Auth' => [
'User' => [
'sn' => [
0 => 'test2'
],
'mail' => [
0 => 'testa@test.fr'
],
'givenname' => [
0 => 'test1'
],
'cn' => [
//0 => 'testa'
0 => 'user1_SUPER'
],
'userpassword' => [
0 => 'test'
]
]
]
];
$this->session($user);
$authType = [
'authType' => 'cn'
];
$this->session($authType);
}
*/
/*
public function authAdminPlus() {
/////$this->authUser('user2_ADMINPLUS', 'test3', 'test4');
$this->authUser('u2ADMINP', 'user2', 'ADMINP');
}
*/
/*
$user = [
'Auth' => [
'User' => [
'sn' => [
0 => 'test4'
],
'mail' => [
0 => 'testz@test.fr'
],
'givenname' => [
0 => 'test3'
],
'cn' => [
//0 => 'testz'
0 => 'user2_ADMINPLUS'
],
'userpassword' => [
0 => 'test'
]
]
]
];
$this->session($user);
$authType = [
'authType' => 'cn'
];
$this->session($authType);
}
*/
public function dataProviderRoles2() { return $this->ROLES2; }
public function authAdmin() {
//////$this->authUser('user3_ADMIN', 'test5', 'test6');
$this->authUser('u3ADMIN', 'user3', 'ADMIN');
}
/*
$user = [
'Auth' => [
'User' => [
'sn' => [
0 => 'test6'
],
'mail' => [
0 => 'teste@test.fr'
],
'givenname' => [
0 => 'test5'
],
'cn' => [
//0 => 'teste'
0 => 'user3_ADMIN'
],
'userpassword' => [
0 => 'test'
]
]
]
];
$this->session($user);
$authType = [
'authType' => 'cn'
];
$this->session($authType);
}
*/
public function authResponsable() {
///////$this->authUser('user4_RESP', 'test7', 'test8');
$this->authUser('u4RESP', 'user4', 'RESP');
}
/*
$user = [
'Auth' => [
'User' => [
'sn' => [
0 => 'test8'
],
'mail' => [
0 => 'testr@test.fr'
],
'givenname' => [
0 => 'test7'
],
'cn' => [
//0 => 'testr'
0 => 'user4_RESP'
],
'userpassword' => [
0 => 'test'
]
]
]
];
$this->session($user);
$authType = [
'authType' => 'cn'
];
$this->session($authType);
}
*/
public function authUtilisateur() { $this->authUtilisateurFromTable(); }
public function authUtilisateurFromTable() {
/////$this->authUser('user5_USER', 'test9', 'test0');
$this->authUser('u5USER', 'user5', 'USER');
}
public function authUtilisateurFromLdap() {
//$this->authUser('_NouvelUtilisateur_username', 'NOUVEL', 'UTILISATEUR');
$this->authUser('_fake_ldap_user_', 'FAKE_LDAP', 'UTILISATEUR');
}
/*
$user = [
'Auth' => [
'User' => [
'sn' => [
0 => 'test0'
],
'mail' => [
0 => 'testt@test.fr'
],
'givenname' => [
0 => 'test9'
],
'cn' => [
//0 => 'testt'
0 => 'user5_USER'
],
'userpassword' => [
0 => 'test'
]
]
]
];
$this->session($user);
$authType = [
'authType' => 'cn'
];
$this->session($authType);
}
*/
//protected function assertResponseContainsIf($role, $condition, $content, $messageIfNot=null) {
//protected function assertResponseContainsIf(string $role, bool $condition, array $contents, $testOpposite=true) {
protected function assertResponseContainsIf($role, $condition, array $contents, $testOpposite=true) {
if ($condition) {
$messageOnFail = 'devrait avoir accès';
$assertMethod = 'assertResponseContains';
}
else {
if (!$testOpposite) return;
$messageOnFail = 'ne devrait PAS avoir accès';
$assertMethod = 'assertResponseNotContains';
}
foreach ($contents as $content=>$endmsg)
$this->$assertMethod($content, "Le profil (rôle) $role $messageOnFail $endmsg");
/*
$this->assertResponseContains($content, 'Le profil (rôle) '.$role.' devrait avoir accès à '. $messageIfNot);
}
else {
$this->assertResponseNotContains($content, 'Le profil (rôle) '.$role.' ne devrait PAS avoir accès à '. $messageIfNot);
}
*/
}
// Test qu'on a bien le nb attendu d'entités dans la vue index
protected function _testNbEntitiesInIndexView($entities_name, $nb_entities, $error_msg=null) {
//$this->get('/emprunts/index');
$this->get("/$entities_name/index");
if (!$error_msg) $error_msg = "Le nombre des $entities_name dans la BD (tel qu'affiché par la vue index) devrait être de $nb_entities !";
$this->assertResponseContains("Liste des $entities_name ($nb_entities)", $error_msg);
}
// Ajout d'entités liées à un matériel, telles que suivis, emprunts, ou documents...
protected function _testAddEntitiesRelatedToMateriel($entity_name, $nb_entities_in_fixture, $data) {
$matos_created_id = 1;
$matos_validated_id = 3;
$entities_name = $entity_name.'s';
// Test qu'on a bien le nb d'entités de la fixture en BD
$nb = $nb_entities_in_fixture;
$this->_testNbEntitiesInIndexView($entities_name, $nb);
/*
//$this->get('/emprunts/index');
$this->get("/$entities_name/index");
$this->assertResponseContains("Liste des $entities_name ($nb)", "Le nombre initial (fixture) des $entities_name dans la BD devrait être de $nb !");
*/
// Ajout d'une 1ère entité (matériel VALIDATED) => OK
$data['materiel_id'] = $matos_validated_id;
$this->assertTextEquals($data['materiel_id'], $matos_validated_id);
//$this->post("/emprunts/add/$matos_validated_id", $data);
$this->post("/$entities_name/add/$matos_validated_id", $data);
$nb++;
$this->_testNbEntitiesInIndexView($entities_name, $nb, "L'ajout d'un $entity_name (1) pour un materiel VALIDATED ne se fait pas correctement alors que ça devrait !");
return;
/*
$this->get("/$entities_name/index");
$this->assertResponseContains("Liste des $entities_name ($nb)", "L'ajout d'un $entity_name (1) pour un materiel VALIDATED ne se fait pas correctement alors que ça devrait !");
*/
// Ajout d'une 2ème entité (matériel VALIDATED) => OK
//$data['materiel_id'] = $matos_validated_id;
//$this->assertTextEquals($data['materiel_id'], $matos_validated_id);
$this->post("/$entities_name/add/$matos_validated_id", $data);
$nb++;
$this->_testNbEntitiesInIndexView($entities_name, $nb, "L'ajout d'un $entity_name (2) pour un materiel VALIDATED ne se fait pas correctement alors que ça devrait !");
/*
$this->get("/$entities_name/index");
$this->assertResponseContains("Liste des $entities_name ($nb)", "L'ajout d'un $entity_name (2) pour un materiel VALIDATED ne se fait pas correctement alors que ça devrait !");
*/
// Ajout d'une 3ème entité (matériel CREATED) => KO
$data['materiel_id'] = $matos_created_id;
$this->assertTextEquals($data['materiel_id'], $matos_created_id);
$this->post("/$entities_name/add/$matos_created_id", $data);
//$nb++;
$this->_testNbEntitiesInIndexView($entities_name, $nb, "L'ajout d'un $entity_name (3) pour un materiel CREATED ne se fait pas correctement alors que ça ne devrait pas !");
/*
$this->get("/$entities_name/index");
$this->assertResponseContains("Liste des $entities_name ($nb)", "L'ajout d'un $entity_name (3) pour un materiel CREATED se fait correctement alors que ça ne devrait pas !");
*/
// Ajout d'une 4ème entité (matériel VALIDATED) => OK
$data['materiel_id'] = $matos_validated_id;
$this->assertTextEquals($data['materiel_id'], $matos_validated_id);
$this->post("/$entities_name/add/$matos_validated_id", $data);
$nb++;
$this->_testNbEntitiesInIndexView($entities_name, $nb, "L'ajout d'un $entity_name (4) pour un materiel VALIDATED ne se fait pas correctement alors que ça devrait !");
/*
$this->get("/$entities_name/index");
$this->assertResponseContains("Liste des $entities_name ($nb)", "L'ajout d'un $entity_name (4) pour un materiel VALIDATED ne se fait pas correctement alors que ça devrait !");
*/
} // testAddEntitiesRelatedToMateriel
protected function inflectEntityName($entities_name) {
//$entities_name = strtolower($entities_name);
switch ($entities_name) {
case 'Materiel': $entities_name = 'Matériel'; break;
case 'Materiels': $entities_name = 'Matériels'; break;
case 'User': $entities_name = 'Utilisateur'; break;
case 'Users': $entities_name = 'Utilisateurs'; break;
case 'SurCategorie': $entities_name = 'Domaine'; break;
case 'SurCategories': $entities_name = 'Domaines'; break;
/*
case 'materiel': $entities_name = 'matériel'; break;
case 'materiels': $entities_name = 'matériels'; break;
case 'user': $entities_name = 'utilisateur'; break;
case 'users': $entities_name = 'utilisateurs'; break;
case 'sur-categorie': $entities_name = 'domaine'; break;
case 'sur-categories': $entities_name = 'domaines'; break;
*/
}
// Par défaut, aucun changement (ex: 'suivis' => 'suivis')
//return $entities_name;
return lcfirst($entities_name);
}
protected function _checkNbEntitiesInIndexViewIsAsExpected($entities_name,$nbentities_expected) {
//$this->get('/materiels/index');
//$entities_name = Inflector::dasherize($entities_name);
//debug("entities1 $entities_name");
$this->get("/$entities_name/index");
//debug($_SESSION);return;
$this->assertResponseOk();
$entities_name = $this->inflectEntityName($entities_name);
//debug("entities2 $entities_name");
$this->assertResponseContains("Liste des $entities_name ($nbentities_expected)", "Le nombre d'entités dans la vue 'index' est incorrect");
}
/**
*
* (EP 20200620)
*
* Test (automatique) de (presque) TOUTES les actions d'un controleur
*
* Appelé par chaque test de controleur en passant en paramètre $entities_name (et le reste par DataProvider)
*
* @return void
*
*/
protected function _testAuthorizationsForAllControllerActions($action, $role_short, $role_long) {
//protected function _testAuthorizationsForAllActionsOfController($entities_name, $action, $role_short, $role_long) {
// Force le rechargement des entités materiel en BD (car on les modifie en cours de route)
//AppController::forceReload();
$entities_name = $this->getEntitiesName();
//debug("entities0 $entities_name");
$IS_MATERIEL = ($entities_name=='Materiels');
//debug("entities_name is $entities_name");
/*
//$controller_name = 'Materiels';
$controller_name = 'App\Controller\\'.$entities_name.'Controller';
//$mc = new MaterielsController();
$c = new $controller_name();
//$entity_name =$c->name;
*/
$c = $this->_getController();
// POUR CHAQUE $action et $role (fournis par le dataProvider) :
$this->d("*******************");
//$this->d(" CONTROLEUR $c->name, ACTION $action, ROLE $role_short");
$this->d(" CONTROLEUR {$c->getName()}, ACTION $action, ROLE $role_short");
$this->d("*******************");
//$this->setUp();
//$this->authSuperAdmin();
$this->authAs($role_long);
// NULL why ?
//debug($_SESSION);return;
$nbentities = $this->getNbEntitiesExpectedInIndexView();
// NULL why ?
//debug($_SESSION);return;
$this->_checkNbEntitiesInIndexViewIsAsExpected($entities_name, $nbentities);
// pas NULL why ?
//debug($_SESSION);return;
// On recupère une entité quelconque de la BD (fixture), peu importe ce que c'est car on va la modifier
$id = $this->_getEntityIdOkForTesting();
if (in_array($action, ['add','index'])) $id=null; // OU $id=0 ?
$getpost = in_array($action, ['view', 'index', 'find', 'printLabelRuban']) ? 'get':'post';
$posted_data = [];
if ($action=='add') $posted_data = $this->getNewEntityWithAllMandatoryFields();
// Si 'edit', on marque le materiel comme ayant été modifié (on change le nom)
if ($action=='edit') {
$e = $c->getEntity($id);
$name_field = $c->getNameFieldLabel();
// On ajoute '(CHANGED)' à la fin du nom de l'entité pour vérifier ensuite qu'elle a bien été modifiée
$posted_data = [
$name_field => $e->$name_field.' (CHANGED)'
];
}
// Quel id pour le matos (associé) ?
// Par défaut (pour MaterielsController) $matos_id et $id sont identiques (confondus)
$matos_id = $id;
$entities_related_to_materiel = ['Documents', 'Emprunts', 'Suivis'];
// Entité associée à un matériel ? (Suivis, Emprunts, Documents...)
//if (!$IS_MATERIEL && $action!='index') {
if ( in_array($entities_name, $entities_related_to_materiel) && $action!='index' ) {
//if ($action=='add') $related_matos_id = $this->getNewEntityWithAllMandatoryFields()->materiel_id;
//$related_matos_id = $this->getMaterielsController()->_getEntityIdOkForTesting();
$actions_with_related_matos_id = ['add'];
//if ($c->name == 'Documents') $actions_with_related_matos_id[] = ['admission','sortie'];
if ($c->getName() == 'Documents') $actions_with_related_matos_id[] = ['admission','sortie'];
if (in_array($action, $actions_with_related_matos_id)) {
// id = celui du matos associé
$id = MaterielsControllerTest::_getEntityIdOkForTesting();
if ($action == 'add') $posted_data['materiel_id'] = $id;
$matos_id = $id;
}
else {
// id = celui de l'entité (suivi, emprunt, document....)
// matos_id = celui associé à l'entité
$e = $this->_getController()->getEntity($id);
if ($e->has('materiel_id')) $matos_id = $e->materiel_id;
}
}
$access_condition = $c->getAccessConditionForActionAndRole($action,$role_short);
//debug("Condition d'accès pour l'action $action et le rôle $role_short"); debug($access_condition);
/*
*
* Test de l'accès à l'action : 3 GRANDS CAS POSSIBLES
*
*/
// Force le rechargement des materiels car ils vont être modifiés par les tests
AppController::forceReload();
/*
if ($access_condition==='default') {
debug("is default");
}
*/
// 1) ACCÈS AUTORISÉ
if ($access_condition===0) {
$this->d("is 0");
//if ($this->DEBUG) {debug($action); debug($id)};
$this->_testExecActionForId($action,$id,$getpost,$posted_data,true,$nbentities);
}
// 2) ACCÈS REFUSÉ
elseif ($access_condition===-1) {
$this->d("is -1");
$this->_testExecActionForId($action,$id,$getpost,$posted_data,false,$nbentities);
}
// 3) ACCÈS AUTORISÉ SOUS CONDITION
// ATTENTION : toujours tester le cas où ca marche (AUTORISÉ) en dernier
// Utile pour des actions telles que 'delete' !!!
elseif (is_array($access_condition)) {
$this->d("is array");
$access_condition_on_status = $access_condition[0];
$access_condition_on_belonging = $access_condition[1];
// 4 cas possibles :
/*
* a) [0,0] => idem cas 1) ci-dessus => accès autorisé (avec matos quelconque)
*/
//if ($access_condition_on_status===0 && $access_condition_on_belonging===0) {
if ([$access_condition_on_status,$access_condition_on_belonging]===[0,0]) {
$this->d("- is [0,0] => equivaut à 0");
$this->_testExecActionForId($action,$id,$getpost,$posted_data,true,$nbentities);
}
/*
* b) [0,1] => on ne teste que l'appartenance, soit 2 tests :
* - (1) on crée un materiel (T,F) => on teste que l'accès être bien AUTORISÉ
* - (2) on crée un materiel (F,T) => on teste que l'accès être bien REFUSÉ, SAUF si le profil est RESP (AUTORISÉ)
*/
elseif ([$access_condition_on_status,$access_condition_on_belonging]===[0,1]) {
$this->d("- is [0,1]");
//$m = $this->Materiels->get($id);
// - (1) (T,F)
$this->_updateMatosBelongingToCurrentUserAndInSameGroup($matos_id, true, false);
$this->_testExecActionForId($action,$id,$getpost,$posted_data,true,$nbentities);
// - (2) (F,T)
$this->_updateMatosBelongingToCurrentUserAndInSameGroup($matos_id, false, true);
// ok seulement pour RESP
$this->_testExecActionForId($action,$id,$getpost,$posted_data,$this->USER_IS_RESP(),$nbentities);
}
/*
* c) [*,0] => on ne teste que le statut, soit 2 tests :
* - (1) on crée un matériel qui A le statut demandé => on teste que l'accès être bien AUTORISÉ
* - (2) on crée un matériel qui n'A PAS le statut demandé => on teste que l'accès être bien REFUSÉ
*/
elseif (is_string($access_condition_on_status) && $access_condition_on_belonging===0) {
$this->d("- is [*,0]");
//$m = $this->Materiels->get($id);
// - (1) statut KO
/*
$this->_updateMatosWithStatusAs($id, $access_condition_on_status, false);
$this->_testExecActionForId($action,$id,false);
*/
// - (2) statut OK
$this->_updateMatosWithStatusAs($matos_id, $access_condition_on_status, true);
$this->_testExecActionForId($action,$id,$getpost,$posted_data,true,$nbentities);
}
/*
* d) [*,1] => Cas général, on teste les 2 conditions, soit 2x2=4 tests
* Les 2 conditions (A-statut et B-appartenance) doivent être vérifiées : A && B (c'est un AND)
* On va donc tester le couple (A,B), ce qui nous donne 3 cas :
*/
elseif (is_string($access_condition_on_status) && $access_condition_on_belonging===1) {
$this->d("- is [*,1]");
//$m = $this->Materiels->get($id);
// (1) (T,F) => accès REFUSÉ
$this->d("(1. TF) should be KO");
$this->_updateMatosWithStatusAs($matos_id, $access_condition_on_status, true);
$this->_updateMatosBelongingToCurrentUserAndInSameGroup($matos_id, false, false);
$m = $this->Materiels->get($matos_id);
$this->d("(1) id is $id, materiel (id, statut, nom_responsable, nom_createur) is : $m->id, $m->status, $m->nom_responsable, $m->nom_createur");
$this->_testExecActionForId($action,$id,$getpost,$posted_data,false,$nbentities);
// (2) (F,T) => accès REFUSÉ
$this->d("(2. FT) should be KO");
//debug($access_condition_on_status);
$this->_updateMatosWithStatusAs($matos_id, $access_condition_on_status, false);
$this->_updateMatosBelongingToCurrentUserAndInSameGroup($matos_id, true, true);
$m = $this->Materiels->get($matos_id);
$this->d("(2) id is $id, materiel (id, statut, nom_responsable, nom_createur) is : $m->id, $m->status, $m->nom_responsable, $m->nom_createur");
$this->_testExecActionForId($action,$id,$getpost,$posted_data,false,$nbentities);
// (3) (F,F) => accès REFUSÉ => inutile de tester ce cas
// (4) (T,T) => accès AUTORISÉ
$this->d("(3. TT) should be OK");
$this->_updateMatosWithStatusAs($matos_id, $access_condition_on_status, true);
$this->_updateMatosBelongingToCurrentUserAndInSameGroup($matos_id, true, $this->USER_IS_RESP());
$m = $this->Materiels->get($matos_id);
$this->d("(3) id is $id, materiel (id, statut, nom_responsable, nom_createur) is : $m->id, $m->status, $m->nom_responsable, $m->nom_createur");
$this->_testExecActionForId($action,$id,$getpost,$posted_data,true,$nbentities);
}
else throw new \ErrorException("La conditions d'accès $access_condition est incorrecte (1)");
}
else throw new \ErrorException("La conditions d'accès $access_condition est incorrecte (2)");
} // testAuthorizationsForAllActionsOfController()
protected function _updateMatosStatusAndBelongingWith($id, $status, $BELONGS=true, $SAMEGROUP=true) {
$this->_updateMatosWithStatusAs($id, $status);
$this->_updateMatosBelongingToCurrentUserAndInSameGroup($id, $BELONGS, $SAMEGROUP);
}
private function _updateMatosWithStatusAs($id, $status, $WITH_SAME_STATUS=true, $DO_SAVE=true) {
//$mc = new MaterielsController();
$mc = $this->getMaterielsController();
$u = $this->getCurrentUser();
$m = $this->getMaterielsTable()->get($id);
//$m = $this->getMateriel($id);
//debug("statut:"); debug($status);
$NOT = FALSE;
// Statut commence par 'NOT' ?
if (strpos($status,'NOT ') === 0) {
$NOT = TRUE;
// on prend le statut après le "NOT " :
$status = substr($status,4);
}
// Condition de statut complexe ? (normalement de la forme "STATUS &&_ou_|| autre_condition")
// => pour simplifier, on ne tient compte que du STATUS (donc le 1er argument)
if ( (strpos($status,'&&')!==FALSE) || (strpos($status,'||')!==FALSE) ) {
//debug("statut complexe '$status'");
$status = explode(' ', $status)[0];
//$status = $status[0];
//debug("=> simplifié en '$status'");
}
//if ($mc->isStatus($status)) {
if (! $mc->isStatus($status))
// On a un cas spécial, du style 'conf.hasPrinter' (sans statut avant, alors que ça pourrait être "VALIDATED && conf.hasPrinter")
// Pour le moment, on ne le traite pas...
//throw new \Exception("Le statut du matériel est incorrect !!!");
;
else {
/*
$m->status = $WITH_SAME_STATUS ? $status : $mc->getNextStatusFrom($status);
if ($NOT) $m->status = $mc->getNextStatusFrom($status);
*/
// MEME statut (par défaut) ?
$m->status = $status;
//debug("bef: $m->status");
// ou STATUT différent ?
if ( ($NOT && $WITH_SAME_STATUS) || (!$NOT && !$WITH_SAME_STATUS) ) $m->status = $mc->getNextStatusFrom($status);
//debug("after: $m->status");
// On sauvegarde le matos modifié
//if (! $this->Materiels->save($m))
//if ($DO_SAVE && !$this->getMaterielsTable()->save($m))
if ($DO_SAVE)
if (! $this->getMaterielsTable()->save($m) )
throw new \Exception("La sauvegarde du materiel modifié ne se fait pas !!!");
//return $m;
}
//else throw new \Exception("Le statut du matériel est incorrect !!!");
return $m;
}
private function _updateMatosBelongingToCurrentUserAndInSameGroup($id, $BELONGS=true, $SAMEGROUP=true, $DO_SAVE=true) {
$u = $this->getCurrentUser();
$m = $this->Materiels->get($id);
// BELONGS ?
$user_name = $BELONGS ? $u->nom : 'inconnu'; // 'user5 USER'
$m->nom_responsable = $user_name;
$m->nom_createur = $user_name;
// SAME GROUP ?
$WRONG_GROUP_ID = 2;
$groupe_thematique_id = $SAMEGROUP ? $u->groupes_thematique_id : $WRONG_GROUP_ID;
$groupe_metier_id = $SAMEGROUP ? $u->groupes_metier_id : $WRONG_GROUP_ID;
$m->groupes_thematique_id = $groupe_thematique_id;
$m->groupes_metier_id = $groupe_metier_id;
//debug($matos);
// On sauvegarde le matos modifié
if ( $DO_SAVE && !$this->Materiels->save($m) )
throw new \Exception("La sauvegarde du materiel modifié ne se fait pas !!!");
return $m;
}
//private function _testExecActionForId($action,$id,$SHOULD_BE_SUCCESS) {
private function _testExecActionForId($action,$id,$getpost,$posted_data,$SHOULD_BE_SUCCESS,$nbentities) {
//debug($this->_flashMessages);
//$entities = 'materiels';
//$entities_name = strtolower($this->getEntitiesName());
//$entities_name = Inflector::dasherize($this->getEntitiesName());
$entities_name = $this->getEntitiesName();
//$entities_name = $this->getEntitiesName();
//$IS_MATERIEL = ($entities_name=='materiels');
$IS_MATERIEL = ($entities_name=='Materiels');
//$getpost = in_array($action, ['add','add_by_copy','edit','delete', 'statusCreated']) ? 'post' : 'get';
//$getpost = in_array($action, ['view', 'index', 'find', 'printLabelRuban']) ? 'get':'post';
//$getpost = in_array($action, ['view', 'index', 'find']) ? 'get':'post';
//$this->post("/materiels/$action/$matos_id");
// Si 'add' ou 'index' => pas d'id
//debug("0"); debug($_SESSION);
//$data = ($action=='add') ? $this->newMaterielWithAllMandatoryFields : [];
//$data = ($action=='add') ? $this->getNewEntityWithAllMandatoryFields() : [];
/*
$data = [];
if ($action=='add') {
$data = $this->getNewEntityWithAllMandatoryFields();
if ($entities_name != 'materiels') $data['materiel_id'] = $id;
}
*/
$exec_action = $action;
if ($action=='add_by_copy') $exec_action='add';
$full_action = "/$entities_name/$exec_action";
//if (! in_array($action, ['add', 'index'])) $full_action .= "/$id";
if (! ($action=='index' || ($action=='add' && $IS_MATERIEL)) ) $full_action .= "/$id";
$this->d("Execution action : \$this->$getpost($full_action, data); (avec data=)"); $this->d($posted_data);
// GET
if ($getpost=='get')
$this->$getpost($full_action);
// POST
else
$this->$getpost($full_action, $posted_data);
/*
if ($SUCCESS) $this->assertNoRedirect();
else $this->assertRedirect();
*/
//$this->get('/materiels/view/2');
//$res = $this->_getBodyAsString();
//$res = $this->_getBodyAsString(); debug($res);
//debug($this->_flashMessages);
//debug($_SESSION);
//debug($flash_message);
// Normalement, l'action devrait avoir été autorisée
if ($SHOULD_BE_SUCCESS) {
$flash_message = null;
$this->assertResponseSuccess();
//if ($entities_name=='materiels' && $action=='printLabelRuban') {
if ($entities_name=='Materiels' && $action=='printLabelRuban') {
/*
$this->assertFileResponse('inventirap_label.label', 'pas de fichier généré');
$this->assertHeader('Content-type', 'application/xml');
$this->assertHeader('Content-Type', 'application/xml');
*/
//var_dump($this->_getBodyAsString());
$filename = 'inventirap_label.label';
$this->assertHeader('Content-Disposition', 'attachment; filename="'.$filename.'"');
//$this->assertHeader('Content-Disposition', "attachment; filename='$filename'");
$msg_error = "L'action $action n'est pas autorisée (pour le role {$this->getUserRole()}) alors qu'elle devrait !!!";
// - DLS :
/*
$this->assertResponseContains("ContinuousLabel", $msg_error);
$this->assertResponseContains("Landscape", $msg_error);
*/
// - DCD :
$this->assertResponseContains("DYMOLabel", $msg_error);
$this->assertResponseContains("19X7-TAPE BLACK/WHITE", $msg_error); // format 19mm
$this->assertResponseContains("Landscape", $msg_error);
}
// GET
if ($getpost == 'get') {
$this->assertResponseOk();
$this->assertResponseNotEmpty();
$this->assertNoRedirect();
if (isset($_SESSION['Flash'])) {
$flash_message = $_SESSION['Flash'];
//$this->assertEquals([], $flash_message);
}
}
// POST
else {
// Nom de l'entité au singulier et en minuscule
$entity_name = substr($entities_name,0,-1);
$entity_name = $this->inflectEntityName($entity_name);
//if ($entity_name=='materiel') $entity_name='matériel';
$c = $this->_getController();
$article = $c->getArticle();
if ($entity_name=='domaine') $article='Le ';
// "Le materiel/suivi/emprunt a bien été"
$expected_flash_message = $article.$entity_name.' a bien été ';
switch($action) {
case 'add':
case 'add_by_copy':
$expected_flash_message .= 'ajouté';
// Vérifier la conséquence de l'action : 1 entité de plus
//debug("entities_name4 is $entities_name");
$this->_checkNbEntitiesInIndexViewIsAsExpected($entities_name, $nbentities+1);
break;
case 'edit':
$expected_flash_message .= 'modifié';
// Vérifier la conséquence de l'action : 1 entité de plus
$e = $c->getEntity($id);
$this->d("entity is"); $this->d($e);
$name_field = $c->getNameFieldLabel();
$this->assertTrue(strpos($e->$name_field,'(CHANGED)')!==false, "L'entité n'a pas été modifiée (action 'edit')");
break;
case 'delete':
$expected_flash_message .= 'supprimé';
// Vérifier la conséquence de l'action : 1 entité de moins
$this->_checkNbEntitiesInIndexViewIsAsExpected($entities_name, $nbentities-1);
break;
case 'statusCreated': $expected_flash_message .= 'rétrogradé au statut CREATED'; break;
case 'statusValidated': $expected_flash_message .= 'validé'; break;
case 'statusTobearchived': $expected_flash_message = "La sortie d'inventaire a bien été demandée"; break;
case 'statusArchived': $expected_flash_message .= "archivé (sorti de l'inventaire)"; break;
case 'setLabelIsPlaced':
case 'setLabelIsNotPlaced':
$verb = ($action=='setLabelIsPlaced') ? 'a' : "n'a pas";
$expected_flash_message = "Je prends note que l'étiquette $verb été collée sur le matériel"; break;
}
$flash_message = isset($_SESSION['Flash']) ? $_SESSION['Flash']['flash'][0]['message']:[];
//if ($flash_message==null) $flash_message = [];
}
$this->d("(2) action $action, flash is:");$this->d($flash_message);
/*
* Test flash message
* (https://book.cakephp.org/3/en/development/testing.html#testing-flash-messages)
*
* If you want to assert the presence of flash messages in the session and not the rendered HTML,
* you can use enableRetainFlashMessages() in your tests
* to retain flash messages in the session so you can write assertions :
*
* $this->enableRetainFlashMessages();
*/
if ($flash_message) {
// Assert a flash message in the 'flash' key.
// Test message partiel
$this->assertTrue(strpos($flash_message, $expected_flash_message) === 0, "Le message flash est incorrect : ($flash_message) au lieu de ($expected_flash_message)");
// Test message complet
$this->assertFlashMessage($expected_flash_message, 'flash');
//$this->assertEquals($expected_flash_message, $flash_message);
}
//$this->assertResponseContains("Matos Test 2 (C)", "L'action $action n'est pas autorisée (pour le role {$this->getUserRole()}) !!!");
// BUG !!!! pourquoi ça marche avec l'action 'view' ???
//$this->assertResponseContains("Désolé, vous n'êtes pas autorisé à accéder à cette zone", "(2)L'action $action n'est pas autorisée (pour le role {$this->getUserRole()}) !!!");
//$this->assertResponseNotContains("Désolé, vous n", "L'action $action n'est pas autorisée (pour le role {$this->getUserRole()}) alors qu'elle le devrait !");
}
// Normalement, l'action devrait avoir été refusée
else {
// 1) Assert redirect
//$this->assertRedirect(['controller' => 'Users', 'action' => 'login']);
//$this->assertRedirect(['controller' => 'Pages', 'action' => 'home']);
// OK
//$this->assertResponseSuccess();
$this->assertResponseEmpty();
//if (!in_array($action,['add_by_copy'])) $this->assertResponseEmpty();
//if ($getpost == 'get') $this->assertRedirect('/');
// MARCHE PAS !!!
//$this->disableErrorHandlerMiddleware();
// OK
//$this->assertResponseCode(302);
// VOIR LE CONTENU DE LA REPONSE HTML
//debug($this->_response); // materiels/view/2
if (!in_array($action,['edit','delete'])) $this->assertRedirect('/');
//if (!in_array($action,['edit','delete'])) $this->assertRedirect('/materiels/view/2');
//if (!in_array($action,['edit','delete'])) $this->assertRedirect('/pages/home');
//if (!in_array($action,['edit','delete'])) $this->assertRedirect('/pages/display');
//var_dump($this->headers['Location']); exit;
// 2) Assert Flash error message (flash message in the 'flash' key)
// Assert a flash messages uses the error element
$this->assertFlashElement('Flash/error');
$expected_flash_message = "Désolé, vous n'êtes pas autorisé à accéder à cette zone.";
//var_dump($flash_message);
// Test message complet
//$this->assertFlashMessage($expected_flash_message);
$this->assertFlashMessage($expected_flash_message, 'flash');
$this->assertSession($expected_flash_message, 'Flash.flash.0.message');
$flash_message = $_SESSION['Flash']['flash'][0]['message'];
$this->assertEquals($expected_flash_message, $flash_message);
//$this->assertTrue(strpos($flash_message, "Désolé, vous n'êtes pas") !== false);
$this->assertTrue(strpos($flash_message, "Désolé, vous n'êtes pas") === 0);
// BUG !!! why ???
//$this->assertResponseContains("Désolé", "L'action $action est autorisée (pour le role {$this->getUserRole()}) alors qu'elle ne le devrait pas !");
}
} // _testExecActionForId()
/*
* Test générique de l'action delete (appelé par chaque controleur de test)
*/
protected function _testActionDeleteEntity($role) {
$action = 'delete';
//$entities_name = strtolower($this->getEntitiesName());
$entities_name = $this->getEntitiesName();
$this->d("*******************");
$this->d(" CONTROLEUR $entities_name, ACTION $action, ROLE $role");
$this->d("*******************");
$this->authAs($role);
$nbentities = $this->getNbEntitiesExpectedInIndexView();
$this->_checkNbEntitiesInIndexViewIsAsExpected($entities_name, $nbentities);
$id = $this->_getEntityIdOkForTesting();
$this->post("$entities_name/delete/$id");
$nbentities--;
$this->_checkNbEntitiesInIndexViewIsAsExpected($entities_name, $nbentities);
}
}