]> git.agnieray.net Git - galette.git/commitdiff
Improve and add tests; some fixes
authorJohan Cwiklinski <johan@x-tnd.be>
Wed, 17 Apr 2024 12:26:13 +0000 (14:26 +0200)
committerJohan Cwiklinski <johan@x-tnd.be>
Thu, 18 Apr 2024 05:46:32 +0000 (07:46 +0200)
12 files changed:
galette/lib/Galette/Entity/Group.php
galette/lib/Galette/Entity/SavedSearch.php
galette/lib/Galette/IO/CsvIn.php
galette/lib/Galette/Repository/Groups.php
galette/lib/Galette/Repository/Titles.php
tests/Galette/Entity/tests/units/Title.php
tests/Galette/IO/tests/units/CsvIn.php
tests/Galette/Repository/tests/units/Contributions.php
tests/Galette/Repository/tests/units/Groups.php
tests/Galette/Repository/tests/units/PaymentTypes.php
tests/Galette/Repository/tests/units/SavedSearches.php [new file with mode: 0644]
tests/Galette/Repository/tests/units/Titles.php [new file with mode: 0644]

index a01629b6ad6c73c2e6a44f2ce5c94df5211482e6..4e0e7518a01b2602e5bc13264275a4cbc2f958f8 100644 (file)
@@ -101,7 +101,39 @@ class Group
             }
         } catch (Throwable $e) {
             Analog::log(
-                'Cannot load group form id `' . $id . '` | ' . $e->getMessage(),
+                'Cannot load group from id `' . $id . '` | ' . $e->getMessage(),
+                Analog::WARNING
+            );
+            throw $e;
+        }
+    }
+
+    /**
+     * Load group from its name
+     *
+     * @param string $group_name Group name
+     *
+     * @return bool
+     */
+    public function loadFromName(string $group_name): bool
+    {
+        global $zdb;
+
+        try {
+            $select = $zdb->select(self::TABLE);
+            $select->where(array('group_name' => $group_name));
+
+            $results = $zdb->execute($select);
+
+            if ($results->count() > 0) {
+                $this->loadFromRS($results->current());
+                return true;
+            } else {
+                return false;
+            }
+        } catch (Throwable $e) {
+            Analog::log(
+                'Cannot load group from name `' . $group_name . '` | ' . $e->getMessage(),
                 Analog::WARNING
             );
             throw $e;
index 2d102f0bcceee0cb5945dbbd34ea6fd0d0154c2d..f4f2158dc12798f335fc7a0cd9c8b5534373e71f 100644 (file)
@@ -200,6 +200,7 @@ class SavedSearch
                 Analog::log('Not stored!', Analog::ERROR);
                 return false;
             }
+            $this->id = $this->zdb->getLastGeneratedValue($this);
             return true;
         } catch (Throwable $e) {
             Analog::log(
index b63d4070aad34f4466a53c5193a2a3f281824a64..5bbd223afe54faba72d987273ce5bc0c99b18001 100644 (file)
@@ -383,7 +383,7 @@ class CsvIn extends Csv implements FileInterface
                             if (!isset($this->langs[$column])) {
                                 $this->addError(
                                     str_replace(
-                                        '%title',
+                                        '%lang',
                                         $column,
                                         _T("Lang %lang does not exists!")
                                     )
@@ -499,6 +499,10 @@ class CsvIn extends Csv implements FileInterface
                             $values[Status::PK] = $this->preferences->pref_statut ?? Status::DEFAULT_STATUS;
                         }
 
+                        if ($this->fields[$col] == 'pref_lang' && empty(trim($column))) {
+                            $values[$this->fields[$col]] = $this->preferences->pref_lang;
+                        }
+
                         $col++;
                     }
                     //import member itself
index 41510b0ea7dd9e40a820020da53923531d840426..f67869e5212296a8374e0d288e39c54175ac3530 100644 (file)
@@ -334,7 +334,7 @@ class Groups
             }
             return true;
         } catch (Throwable $e) {
-            $te = clone $e;
+            $te = $e;
             if ($transaction === false) {
                 $zdb->connection->rollBack();
             }
@@ -455,7 +455,7 @@ class Groups
             [Adherent::PK]
         )->join(
             array('status' => PREFIX_DB . Status::TABLE),
-            'a.' . Status::PK . '=status.' . Status::PK,
+            'adh.' . Status::PK . '=status.' . Status::PK,
             array('priorite_statut')
         )->join(
             array('b' => PREFIX_DB . Group::GROUPSUSERS_TABLE),
index 06a550153319cf2fd25c4fc682b6332e2006903b..1298c957c4a13eba58d65dba8ed2b8bb16dbd75b 100644 (file)
@@ -144,25 +144,4 @@ class Titles
             throw $e;
         }
     }
-
-    /**
-     * Get translated title short version
-     *
-     * @param integer $title The title id to retrieve
-     *
-     * @return string
-     */
-    public static function getTitle(int $title): string
-    {
-        global $zdb;
-
-        $select = $zdb->select(self::TABLE);
-        $select->limit(1)
-            ->where(array(self::PK => $title));
-
-        $results = $zdb->execute($select);
-        $result = $results->current();
-        $res = $result->short_label;
-        return _T($res);
-    }
 }
index addd671b0c6edde1442a35e2e174f5fb05b8746a..559016db056385e934351efb55da7cf105df46f4 100644 (file)
@@ -87,12 +87,6 @@ class Title extends TestCase
         global $zdb;
         $zdb = $this->zdb;
 
-        $titles = new \Galette\Repository\Titles($this->zdb);
-        if (count($titles->getList()) === 0) {
-            $res = $titles->installInit();
-            $this->assertTrue($res);
-        }
-
         $title = new \Galette\Entity\Title();
 
         $title->short = 'Te.';
index 3172ec14bc6f73599056c4e63514ce5324dca996..31d5d5e413add7658339e7f0896abfee99676026 100644 (file)
@@ -181,10 +181,19 @@ class CsvIn extends GaletteTestCase
 
         if ($count_before != $count_after) {
             foreach ($list as $member) {
+                if (!isset($members_list[$member->fingerprint])) {
+                    continue;
+                }
                 $created = $members_list[$member->fingerprint];
                 foreach ($fields as $field) {
                     if (property_exists($member, $field)) {
-                        $this->assertEquals($created[$field], $member->$field);
+                        if ($field === \Galette\Entity\Status::PK && $created[$field] === null) {
+                            $this->assertNotNull($member->$field);
+                        } else if ($field === 'pref_lang' && $created[$field] === null) {
+                            $this->assertNotNull($member->$field);
+                        } else {
+                            $this->assertEquals($created[$field], $member->$field);
+                        }
                     } else {
                         //manage dynamic fields
                         $matches = [];
@@ -250,6 +259,209 @@ class CsvIn extends GaletteTestCase
         $count_after = 10;
 
         $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //test status import
+        $fields = ['nom_adh', 'ville_adh', 'fingerprint', \Galette\Entity\Status::PK];
+        $file_name = 'test-import-status-ko.csv';
+        $flash_messages = [
+            'error_detected' => [
+                'File does not comply with requirements.',
+                'Status 42 does not exists!'
+            ]
+        ];
+        $members_list = [
+            'FAKER_STATUS' => [
+                'nom_adh' => 'Status tests name',
+                'ville_adh' => 'Status tests city',
+                'fingerprint' => 'FAKER_STATUS',
+                \Galette\Entity\Status::PK => 42 //non-existing status
+            ]
+        ];
+        $count_before = 10;
+        $count_after = 10;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        $members_list['FAKER_STATUS'][\Galette\Entity\Status::PK] = 1; //existing status
+        $file_name = 'test-import-status-ok.csv';
+        $flash_messages = [
+            'success_detected' => ["File '$file_name' has been successfully imported :)"]
+        ];
+        $count_after = 11;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //create with default status
+        $members_list = [
+            'FAKER_DEF_STATUS' => [
+                'nom_adh' => 'Member with default status',
+                'ville_adh' => 'Member with default status city',
+                'fingerprint' => 'FAKER_DEF_STATUS',
+                \Galette\Entity\Status::PK => null //no specified status
+            ]
+        ];
+        $file_name = 'test-import-default-status.csv';
+        $flash_messages = [
+            'success_detected' => ["File '$file_name' has been successfully imported :)"]
+        ];
+        $count_before = 11;
+        $count_after = 12;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //check created member
+        $select = $this->zdb->select(\Galette\Entity\Adherent::TABLE);
+        $select->where(['fingerprint' => 'FAKER_DEF_STATUS']);
+        $result = $this->zdb->execute($select)->current();
+        $this->assertSame(
+            (int)($this->preferences->pref_statut ?? \Galette\Entity\Status::DEFAULT_STATUS),
+            $result[\Galette\Entity\Status::PK]
+        );
+
+        //test title import
+        $fields = ['nom_adh', 'ville_adh', 'fingerprint', 'titre_adh'];
+        $file_name = 'test-import-title-ko.csv';
+        $flash_messages = [
+            'error_detected' => [
+                'File does not comply with requirements.',
+                'Title 42 does not exists!'
+            ]
+        ];
+        $members_list = [
+            'FAKER_TITLE' => [
+                'nom_adh' => 'Status tests name',
+                'ville_adh' => 'Status tests city',
+                'fingerprint' => 'FAKER_TITLE',
+                'titre_adh' => 42 //non-existing title
+            ]
+        ];
+        $count_before = 12;
+        $count_after = 12;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        $members_list['FAKER_TITLE']['titre_adh'] = \Galette\Entity\Title::MR; //existing title
+        $file_name = 'test-import-title-ok.csv';
+        $flash_messages = [
+            'success_detected' => ["File '$file_name' has been successfully imported :)"]
+        ];
+        $count_after = 13;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //test email unicity
+        $fields = ['nom_adh', 'email_adh', 'fingerprint'];
+        $file_name = 'test-import-email-duplicate.csv';
+        $flash_messages = [
+            'error_detected' => [
+                'File does not comply with requirements.',
+                'Email address mail@domain.com is already used! (from another member in import)'
+            ]
+        ];
+        $members_list = [
+            'FAKER_MAIL_1' => [
+                'nom_adh' => 'Member email 1',
+                'email_adh' => 'mail@domain.com',
+                'fingerprint' => 'FAKER_MAIL_1'
+            ],
+            'FAKER_MAIL_12' => [
+                'nom_adh' => 'Member email 2',
+                'email_adh' => 'mail@domain.com',
+                'fingerprint' => 'FAKER_MAIL_2'
+            ]
+        ];
+        $count_before = 13;
+        $count_after = 13;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        $file_name = 'test-import-email-ok.csv';
+        $flash_messages = [
+            'success_detected' => ["File '$file_name' has been successfully imported :)"]
+        ];
+        $members_list = [
+            'FAKER_MAIL_1' => [
+                'nom_adh' => 'Member email 1',
+                'email_adh' => 'mail@domain.com',
+                'fingerprint' => 'FAKER_MAIL_1'
+            ]
+        ];
+        $count_before = 13;
+        $count_after = 14;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //get created member
+        $select = $this->zdb->select(\Galette\Entity\Adherent::TABLE);
+        $select->where(['fingerprint' => 'FAKER_MAIL_1']);
+        $result = $this->zdb->execute($select)->current();
+        $this->assertSame('mail@domain.com', $result['email_adh']);
+
+        $file_name = 'test-import-email-duplicate-again.csv';
+        $flash_messages = [
+            'error_detected' => [
+                'File does not comply with requirements.',
+                'Email address mail@domain.com is already used! (from member ' . $result['id_adh'] . ')'
+            ]
+        ];
+        $members_list = [
+            'FAKER_MAIL_12' => [
+                'nom_adh' => 'Member email 2',
+                'email_adh' => 'mail@domain.com',
+                'fingerprint' => 'FAKER_MAIL_2'
+            ]
+        ];
+        $count_before = 14;
+        $count_after = 14;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //test lang import
+        $fields = ['nom_adh', 'ville_adh', 'fingerprint', 'pref_lang'];
+        $file_name = 'test-import-lang-ko.csv';
+        $flash_messages = [
+            'error_detected' => [
+                'File does not comply with requirements.',
+                'Lang NO_EX does not exists!'
+            ]
+        ];
+        $members_list = [
+            'FAKER_LANG' => [
+                'nom_adh' => 'Lang tests name',
+                'ville_adh' => 'Lang tests city',
+                'fingerprint' => 'FAKER_LANG',
+                'pref_lang' => 'NO_EX' //non-existing lang
+            ]
+        ];
+        $count_before = 14;
+        $count_after = 14;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        $members_list['FAKER_LANG']['pref_lang'] = 'fr_FR'; //existing title
+        $file_name = 'test-import-lang-ok.csv';
+        $flash_messages = [
+            'success_detected' => ["File '$file_name' has been successfully imported :)"]
+        ];
+        $count_after = 15;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //create with default lang
+        $members_list = [
+            'FAKER_DEF_LANG' => [
+                'nom_adh' => 'Member with default lang',
+                'ville_adh' => 'Member with default lang city',
+                'fingerprint' => 'FAKER_DEF_LANG',
+                'pref_lang' => null //no specified lang
+            ]
+        ];
+        $file_name = 'test-import-default-lang.csv';
+        $flash_messages = [
+            'success_detected' => ["File '$file_name' has been successfully imported :)"]
+        ];
+        $count_before = 15;
+        $count_after = 16;
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+
+        //check created member
+        $select = $this->zdb->select(\Galette\Entity\Adherent::TABLE);
+        $select->where(['fingerprint' => 'FAKER_DEF_LANG']);
+        $result = $this->zdb->execute($select)->current();
+        $this->assertSame(
+            $this->preferences->pref_lang,
+            $result['pref_lang']
+        );
     }
 
     /**
@@ -546,6 +758,151 @@ class CsvIn extends GaletteTestCase
         $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
     }
 
+    /**
+     * Test non existing file
+     *
+     * @return void
+     */
+    public function testNoFile(): void
+    {
+        $cin = new \Galette\IO\CsvIn($this->zdb);
+        $this->assertSame(
+            \Galette\IO\FileInterface::INVALID_FILE,
+            $cin->import(
+                $this->zdb,
+                $this->preferences,
+                $this->history,
+                'non-existing-file.csv',
+                $this->members_fields,
+                $this->members_fields_cats,
+                true
+            )
+        );
+        $this->assertSame(
+            ['File non-existing-file.csv cannot be open!'],
+            $cin->getErrors()
+        );
+    }
+
+    /**
+     * Test empty file
+     *
+     * @return void
+     */
+    public function testEmptyFile(): void
+    {
+        $fields = ['nom_adh', 'ville_adh', 'fingerprint'];
+        $file_name = 'test-empty-file.csv';
+        $flash_messages = [
+            'error_detected' => [
+                'File does not comply with requirements.',
+                'File is empty!'
+            ]
+        ];
+
+        $members_list = [];
+        $count_before = 0;
+        $count_after = 0;
+
+        $this->doImportFileTest($fields, $file_name, $flash_messages, $members_list, $count_before, $count_after);
+    }
+
+    /**
+     * Test missing columns
+     *
+     * @return void
+     */
+    public function testMissingColumn(): void
+    {
+        $csvin = new \Galette\IO\CsvIn($this->zdb);
+
+        $fields = ['nom_adh', 'ville_adh', 'fingerprint'];
+        $file_name = 'test-import-missing-column.csv';
+        $this->getModel($fields);
+
+        $contents = "\"" . implode("\";\"", $fields) . "\"\r\n";
+        $fields = ['nom_adh', 'fingerprint'];
+        $members_list = $this->getMemberData1();
+
+        foreach ($members_list as $member) {
+            $amember = [];
+            foreach ($fields as $field) {
+                $amember[$field] = $member[$field];
+            }
+            $contents .= "\"" . implode("\";\"", $amember) . "\"\r\n";
+        }
+
+        $path = GALETTE_CACHE_DIR . $file_name;
+        $this->assertIsInt(file_put_contents($path, $contents));
+        $_FILES['new_file'] = [
+            'error' => UPLOAD_ERR_OK,
+            'name'      => $file_name,
+            'tmp_name'  => $path,
+            'size'      => filesize($path)
+        ];
+        $this->assertTrue($csvin->store($_FILES['new_file'], true));
+        $this->assertTrue(file_exists($csvin->getDestDir() . $csvin->getFileName()));
+
+        $this->assertSame(
+            \Galette\IO\FileInterface::INVALID_FILE,
+            $csvin->import(
+                $this->zdb,
+                $this->preferences,
+                $this->history,
+                $file_name,
+                $this->members_fields,
+                $this->members_fields_cats,
+                true
+            )
+        );
+        $this->assertSame(
+            ['Fields count mismatch... There should be 3 fields and there are 2 (row 1)'],
+            $csvin->getErrors()
+        );
+
+        $csvin = new \Galette\IO\CsvIn($this->zdb);
+        $file_name = 'test-import-missing-column-headers.csv';
+        $fields = ['nom_adh', 'fingerprint'];
+        $members_list = $this->getMemberData1();
+
+        $contents = "\"" . implode("\";\"", $fields) . "\"\r\n";
+        foreach ($members_list as $member) {
+            $amember = [];
+            foreach ($fields as $field) {
+                $amember[$field] = $member[$field];
+            }
+            $contents .= "\"" . implode("\";\"", $amember) . "\"\r\n";
+        }
+
+        $path = GALETTE_CACHE_DIR . $file_name;
+        $this->assertIsInt(file_put_contents($path, $contents));
+        $_FILES['new_file'] = [
+            'error' => UPLOAD_ERR_OK,
+            'name'      => $file_name,
+            'tmp_name'  => $path,
+            'size'      => filesize($path)
+        ];
+        $this->assertTrue($csvin->store($_FILES['new_file'], true));
+        $this->assertTrue(file_exists($csvin->getDestDir() . $csvin->getFileName()));
+
+        $this->assertSame(
+            \Galette\IO\FileInterface::INVALID_FILE,
+            $csvin->import(
+                $this->zdb,
+                $this->preferences,
+                $this->history,
+                $file_name,
+                $this->members_fields,
+                $this->members_fields_cats,
+                true
+            )
+        );
+        $this->assertSame(
+            ['Fields count mismatch... There should be 3 fields and there are 2 (row 0)'],
+            $csvin->getErrors()
+        );
+    }
+
     /**
      * Get first set of member data
      *
index 18d09815fc4d9076d29a03f788ffba3d583a862e..03f81a052efb4d9bf2d3b1fdd74a4880f81d14e8 100644 (file)
@@ -214,6 +214,8 @@ class Contributions extends GaletteTestCase
         $this->assertCount(1, $list);
         $contrib = array_pop($list);
         $this->assertFalse($contrib instanceof \Galette\Entity\Contribution);
+
+        $this->assertFalse($contributions->getArrayList([]));
     }
 
     /**
index aacfd9bf7ba44b33f2d00bc88762ea7472757b38..21c8c28cf6a806c1f2fdd1bbc123def561f6d53e 100644 (file)
@@ -60,6 +60,11 @@ class Groups extends GaletteTestCase
             \Laminas\Db\Adapter\Adapter::QUERY_MODE_EXECUTE
         );
 
+        $zdb->db->query(
+            'TRUNCATE TABLE ' . PREFIX_DB . \Galette\Entity\Group::GROUPSUSERS_TABLE,
+            \Laminas\Db\Adapter\Adapter::QUERY_MODE_EXECUTE
+        );
+
         $groups = self::groupsProvider();
         foreach ($groups as $group) {
             foreach ($group['children'] as $child) {
@@ -270,4 +275,88 @@ class Groups extends GaletteTestCase
         $this->assertFalse(\Galette\Repository\Groups::isUnique($this->zdb, 'Nord', $france));
         $this->assertTrue(\Galette\Repository\Groups::isUnique($this->zdb, 'Creuse', $france));
     }
+
+    /**
+     * Test members/groups
+     *
+     * @return void
+     */
+    public function testMembersGroups(): void
+    {
+        $groups = self::groupsProvider();
+        foreach ($groups as $group) {
+            $this->testCreateGroups($group['parent_name'], $group['children']);
+        }
+
+        $france = new \Galette\Entity\Group();
+        $this->assertTrue($france->loadFromName('France'));
+
+        $allemagne = new \Galette\Entity\Group();
+        $this->assertTrue($allemagne->loadFromName('Allemagne'));
+
+        $member = $this->getMemberOne();
+        $member->loadGroups();
+        $this->assertSame([], $member->managed_groups);
+        $this->assertSame([], $member->groups);
+
+        //add member to France and Allemagne groups, as simple member
+        $this->assertTrue(
+            \Galette\Repository\Groups::addMemberToGroups(
+                $member,
+                [
+                    sprintf('%s|%s', $france->getId(), $france->getName()),
+                    sprintf('%s|%s', $allemagne->getId(), $allemagne->getName())
+                ]
+            )
+        );
+
+        $member->loadGroups();
+        $this->assertSame([], $member->managed_groups);
+        $this->assertCount(2, $member->groups);
+
+        //Add as manager of France
+        $this->assertTrue(
+            \Galette\Repository\Groups::addMemberToGroups(
+                $member,
+                [
+                    sprintf('%s|%s', $france->getId(), $france->getName())
+                ],
+                true
+            ),
+        );
+
+        $member->loadGroups();
+        $this->assertCount(1, $member->managed_groups);
+        $this->assertCount(2, $member->groups);
+
+        $member2 = $this->getMemberTwo();
+        //Add as manager of France
+        $this->assertTrue(
+            \Galette\Repository\Groups::addMemberToGroups(
+                $member2,
+                [
+                    sprintf('%s|%s', $france->getId(), $france->getName())
+                ],
+                true
+            ),
+        );
+
+        $member2->loadGroups();
+        $this->assertCount(1, $member2->managed_groups);
+        $this->assertCount(0, $member2->groups);
+
+        $this->logSuperAdmin();
+        $this->login->impersonate($member2->id);
+
+        $groups = new \Galette\Repository\Groups($this->zdb, $this->login);
+        $users = $groups->getManagerUsers([$allemagne->getId()]);
+        $this->assertSame([$member->id], $users);
+        $users = $groups->getManagerUsers([$france->getId()]);
+        $this->assertSame([$member->id], $users);
+
+        \Galette\Repository\Groups::removeMemberFromGroups($member->id);
+        $member->loadGroups();
+        $this->assertSame([], $member->managed_groups);
+        $this->assertSame([], $member->groups);
+    }
 }
index 89cf83ed9b80fc8dfe18c23b3d25893ef314698c..4522111c83f22d9340ad5a9733ffe63f857de484 100644 (file)
@@ -111,7 +111,6 @@ class PaymentTypes extends GaletteTestCase
             $this->assertGreaterThanOrEqual(
                 6,
                 $result->last_value,
-                6,
                 'Incorrect payment types sequence ' . $result->last_value
             );
         }
diff --git a/tests/Galette/Repository/tests/units/SavedSearches.php b/tests/Galette/Repository/tests/units/SavedSearches.php
new file mode 100644 (file)
index 0000000..851dd33
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * Copyright © 2003-2024 The Galette Team
+ *
+ * This file is part of Galette (https://galette.eu).
+ *
+ * Galette 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.
+ *
+ * Galette 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 Galette. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Galette\Repository\test\units;
+
+use Galette\GaletteTestCase;
+
+/**
+ * Saved searches repository tests
+ *
+ * @author Johan Cwiklinski <johan@x-tnd.be>
+ */
+class SavedSearches extends GaletteTestCase
+{
+    protected int $seed = 20240417150507;
+
+    /**
+     * Tear down tests
+     *
+     * @return void
+     */
+    public function tearDown(): void
+    {
+        $this->zdb->db->query(
+            'TRUNCATE TABLE ' . PREFIX_DB . \Galette\Entity\SavedSearch::TABLE,
+            \Laminas\Db\Adapter\Adapter::QUERY_MODE_EXECUTE
+        );
+        parent::tearDown();
+    }
+
+    /**
+     * Test getList
+     *
+     * @return void
+     * @throws \Throwable
+     */
+    public function testGetList(): void
+    {
+        global $i18n; // globals :(
+        $i18n = $this->i18n;
+        $i18n->changeLanguage('en_US');
+
+        $saved = new \Galette\Entity\SavedSearch($this->zdb, $this->login);
+        $searches = new \Galette\Repository\SavedSearches($this->zdb, $this->login);
+
+        $post = [
+            'parameters'    => [
+                'filter_str'        => '',
+                'field_filter'      => 0,
+                'membership_filter' => 0,
+                'filter_account'    => 0,
+                'roup_filter'       => 0,
+                'email_filter'      => 5,
+                'nbshow'            => 10
+            ],
+            'form'          => 'Adherent',
+            'name'          => 'Simple search'
+        ];
+
+        //store search
+        $this->assertTrue($saved->check($post));
+        $this->assertTrue($saved->store());
+        $sid_1 = $saved->id;
+
+        $list = $searches->getList(true);
+        $this->assertIsArray($list);
+        $this->assertCount(1, $list);
+        $this->assertSame(1, $searches->getCount());
+
+        $result = array_pop($list);
+        $this->assertInstanceOf(\Galette\Entity\SavedSearch::class, $result);
+
+        $list = $searches->getList(false);
+        $this->assertInstanceOf(\Laminas\Db\ResultSet\ResultSet::class, $list);
+        $this->assertNotInstanceOf(\Galette\Entity\SavedSearch::class, $list->current());
+
+        //another one
+        $post['name'] = 'Another search';
+        $this->assertTrue($saved->store());
+        $sid_2 = $saved->id;
+        $this->assertCount(2, $searches->getList(true));
+        $this->assertSame(2, $searches->getCount());
+
+        $post['name'] = 'Last one';
+        $this->assertTrue($saved->store());
+        $sid_3 = $saved->id;
+        $this->assertCount(3, $searches->getList(true));
+        $this->assertSame(3, $searches->getCount());
+
+        $this->assertFalse($searches->remove([], $this->history));
+        $this->assertTrue($searches->remove($sid_2, $this->history));
+        $list = $searches->getList(true);
+        $this->assertCount(2, $list);
+        foreach ($list as $entry) {
+            $this->assertNotSame($sid_2, $entry->id);
+        }
+
+        $this->assertTrue($searches->remove([$sid_1, $sid_3], $this->history));
+        $list = $searches->getList(true);
+        $this->assertCount(0, $list);
+    }
+}
diff --git a/tests/Galette/Repository/tests/units/Titles.php b/tests/Galette/Repository/tests/units/Titles.php
new file mode 100644 (file)
index 0000000..a660bd5
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * Copyright © 2003-2024 The Galette Team
+ *
+ * This file is part of Galette (https://galette.eu).
+ *
+ * Galette 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.
+ *
+ * Galette 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 Galette. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Galette\Repository\test\units;
+
+use Galette\GaletteTestCase;
+
+/**
+ * Payment types repository tests
+ *
+ * @author Johan Cwiklinski <johan@x-tnd.be>
+ */
+class Titles extends GaletteTestCase
+{
+    protected int $seed = 20240417170519;
+
+    private array $remove = [];
+
+    /**
+     * Set up tests
+     *
+     * @return void
+     */
+    public function setUp(): void
+    {
+        parent::setUp();
+
+        $titles = new \Galette\Repository\Titles($this->zdb);
+        $res = $titles->installInit();
+        $this->assertTrue($res);
+    }
+
+    /**
+     * Tear down tests
+     *
+     * @return void
+     */
+    public function tearDown(): void
+    {
+        parent::tearDown();
+        $this->deleteTitles();
+    }
+
+    /**
+     * Delete payment type
+     *
+     * @return void
+     */
+    private function deleteTitles(): void
+    {
+        if (is_array($this->remove) && count($this->remove) > 0) {
+            $delete = $this->zdb->delete(\Galette\Entity\Title::TABLE);
+            $delete->where->in(\Galette\Entity\Title::PK, $this->remove);
+            $this->zdb->execute($delete);
+        }
+
+        //Clean logs
+        $this->zdb->db->query(
+            'TRUNCATE TABLE ' . PREFIX_DB . \Galette\Core\History::TABLE,
+            \Laminas\Db\Adapter\Adapter::QUERY_MODE_EXECUTE
+        );
+    }
+
+    /**
+     * Test getList
+     *
+     * @return void
+     */
+    public function testGetList(): void
+    {
+        $titles = new \Galette\Repository\Titles($this->zdb);
+
+        $list = $titles->getList();
+        $this->assertCount(2, $list);
+
+        if ($this->zdb->isPostgres()) {
+            $select = $this->zdb->select(\Galette\Entity\PaymentType::TABLE . '_id_seq');
+            $select->columns(['last_value']);
+            $results = $this->zdb->execute($select);
+            $result = $results->current();
+            $this->assertGreaterThanOrEqual(1, $result->last_value, 'Incorrect titles sequence');
+        }
+
+        //add another one
+        $title = new \Galette\Entity\Title();
+        $title->short = 'Te.';
+        $title->long = 'Test';
+        $this->assertTrue($title->store($this->zdb));
+
+        $id = $title->id;
+        $this->remove[] = $id;
+
+        $list = $titles->getList();
+        $this->assertCount(3, $list);
+
+        //reinstall payment types
+        $titles->installInit();
+
+        $list = $titles->getList();
+        $this->assertCount(2, $list);
+
+        if ($this->zdb->isPostgres()) {
+            $select = $this->zdb->select(\Galette\Entity\PaymentType::TABLE . '_id_seq');
+            $select->columns(['last_value']);
+            $results = $this->zdb->execute($select);
+            $result = $results->current();
+            $this->assertGreaterThanOrEqual(
+                1,
+                $result->last_value,
+                'Incorrect title sequence ' . $result->last_value
+            );
+        }
+    }
+}