From 08b992b006fbaa99b65b86851afe949636f10f65 Mon Sep 17 00:00:00 2001 From: divyesh000 Date: Fri, 10 May 2024 18:08:38 +0400 Subject: [PATCH 1/4] write tests for Store model --- src/models/Comment.php | 2 +- tests/StoreTest.php | 74 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tests/StoreTest.php diff --git a/src/models/Comment.php b/src/models/Comment.php index 286f5dad..09c23c0c 100644 --- a/src/models/Comment.php +++ b/src/models/Comment.php @@ -123,7 +123,7 @@ public function save(): bool // remove created_date (let database handle it) unset($data['created_date']); - // perform insertion to the review table + // perform insertion to the comment table $inserted_id = $this->insert($data, $this->table); if ($inserted_id === null) { diff --git a/tests/StoreTest.php b/tests/StoreTest.php new file mode 100644 index 00000000..39cceed0 --- /dev/null +++ b/tests/StoreTest.php @@ -0,0 +1,74 @@ +dummy_store = new Store( + phone_no: "12345678", // Phone number + address: new Location("Royal", "Curepipe", 1) // Address + ); + + $success = $this->dummy_store->save(); + if (!$success) { + throw new Exception('Unable to save store'); + } + + } + + public function tearDown(): void + { + // Clean up the dummy store object after each test + if ($this->dummy_store) { + $this->dummy_store = null; + } + + // clear all data from store tables + self::query('DELETE FROM store_product; DELETE FROM store;'); + } + + public function testSave(): void + { + // Test saving a valid store + $saved = $this->dummy_store->save(); + self::assertTrue($saved); + + // Test saving an invalid store (phone number too short) + $this->dummy_store->setPhoneNo('123'); // Short phone number + $saved = $this->dummy_store->save(); + self::assertFalse($saved); + } + + public function testValidate(): void + { + // Test for a valid store + $errors = $this->dummy_store->validate(); + self::assertEmpty($errors); + + // Test for an invalid phone number (too short) + $this->dummy_store->setPhoneNo('123'); // Short phone number + $errors = $this->dummy_store->validate(); + self::assertArrayHasKey('phone_no', $errors); + } + + public function testGetProductStock(): void + { + // Assuming product_id 1 is present in the store + $product_id = 1; + $stock_level = $this->dummy_store->getProductStock($product_id); + self::assertGreaterThanOrEqual(0, $stock_level); + } +} From b6a12c483bb89e80718134e7b55bdb41c357bc43 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Sat, 18 May 2024 13:25:47 +0400 Subject: [PATCH 2/4] validate longitude and latitude, use empty to check if errors are present in save() --- src/models/Store.php | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/models/Store.php b/src/models/Store.php index 9513182e..e230aa8f 100644 --- a/src/models/Store.php +++ b/src/models/Store.php @@ -96,7 +96,7 @@ public static function getAll(): array */ public function save(): bool { - if (!$this->validate()) { + if (!empty($this->validate())) { return false; } @@ -126,7 +126,6 @@ public function save(): bool public function validate(): array { - $errors = []; $errors = $this->address->validate(); // Perform phone number length check @@ -134,6 +133,16 @@ public function validate(): array $errors ['phone_no'] = "Phone number must be at least 7 characters long"; } + // Validate latitude and longitude + $latitude = $this->address->getLatitude(); + $longitude = $this->address->getLongitude(); + + if ($latitude == null || $longitude == null || + ($latitude < -90 || $latitude > 90 || + $longitude < -180 || $longitude > 180)) { + $errors['coordinates'] = "Invalid latitude or longitude."; + } + return $errors; } @@ -157,17 +166,17 @@ public function getProducts(): array $results = self::query($query, $params); $products = []; - foreach ($results as $result) { - $products[] = new Product( - $result->product_id, - $result->name, - $result->calories, - $result->img_url, - $result->img_alt_text, - $result->category, - $result->price, - $result->description - ); + foreach ($results as $result) { + $products[] = new Product( + $result->product_id, + $result->name, + $result->calories, + $result->img_url, + $result->img_alt_text, + $result->category, + $result->price, + $result->description + ); } return $products; } From d43705cee63e2884eb0559be1d706d68f4cf4ea1 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Sat, 18 May 2024 13:26:52 +0400 Subject: [PATCH 3/4] add missing latitude and longitude to store object in setUp, make error messages more helpful --- tests/StoreTest.php | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/StoreTest.php b/tests/StoreTest.php index 39cceed0..16cac1dd 100644 --- a/tests/StoreTest.php +++ b/tests/StoreTest.php @@ -10,8 +10,12 @@ class StoreTest extends TestCase { use Database; + private ?Store $dummy_store; + /** + * @throws Exception + */ public function setUp(): void { parent::setUp(); @@ -19,14 +23,27 @@ public function setUp(): void // Initialize a dummy store object for testing $this->dummy_store = new Store( phone_no: "12345678", // Phone number - address: new Location("Royal", "Curepipe", 1) // Address + address: new Location( + street: "Royal", + city: "Curepipe", + district_id: 1, + latitude: 50, + longitude: 50 + ) ); - + $success = $this->dummy_store->save(); if (!$success) { - throw new Exception('Unable to save store'); - } + $errors = $this->dummy_store->validate(); + $error_msg = "Unable to save store to database. "; + if (!empty($errors)) { + $error_msg .= "Errors: " . implode(',', $errors); + } else { + $error_msg .= "Attributes seem to be ok as per validate()."; + } + throw new Exception($error_msg); + } } public function tearDown(): void @@ -37,7 +54,7 @@ public function tearDown(): void } // clear all data from store tables - self::query('DELETE FROM store_product; DELETE FROM store;'); + self::query('DELETE FROM store;'); } public function testSave(): void From 985dfe25e58e3afa9af03d45a9cef43a4a5204bf Mon Sep 17 00:00:00 2001 From: divyesh000 Date: Sat, 18 May 2024 20:45:16 +0400 Subject: [PATCH 4/4] use data providers for testSave and testValidate methods, adding more test cases for phone number and address validationgit --- tests/StoreTest.php | 77 ++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/tests/StoreTest.php b/tests/StoreTest.php index 16cac1dd..a560c7d9 100644 --- a/tests/StoreTest.php +++ b/tests/StoreTest.php @@ -57,35 +57,70 @@ public function tearDown(): void self::query('DELETE FROM store;'); } - public function testSave(): void + /** + * @dataProvider saveDataProvider + * @param string $phone_no + * @param Location $address + * @param bool $expected_success + * @throws Exception + */ + public function testSave(string $phone_no, Location $address, bool $expected_success) { - // Test saving a valid store - $saved = $this->dummy_store->save(); - self::assertTrue($saved); - - // Test saving an invalid store (phone number too short) - $this->dummy_store->setPhoneNo('123'); // Short phone number - $saved = $this->dummy_store->save(); - self::assertFalse($saved); + $this->dummy_store->setPhoneNo($phone_no); + $this->dummy_store->setAddress($address); + + $success = $this->dummy_store->save(); + + $this->assertEquals($expected_success, $success); } - public function testValidate(): void + public static function saveDataProvider(): array { - // Test for a valid store - $errors = $this->dummy_store->validate(); - self::assertEmpty($errors); + return [ + // Valid phone number, valid address + ["1234567890", new Location("Royal", "Curepipe", 1, 50, 50), true], + // Invalid phone number (less than 7 characters) + ["123456", new Location("Royal", "Curepipe", 1, 50, 50), false], + // Empty phone number + ["", new Location("Royal", "Curepipe", 1, 50, 50), false], + // Invalid characters in phone number + ["123abc", new Location("Royal", "Curepipe", 1, 50, 50), false], + // Valid address with valid latitude/longitude + ["1234567890", new Location("Royal", "Curepipe", 1, 50, 50), true], + // Invalid latitude value (out of range) + ["1234567890", new Location("Royal", "Curepipe", 1, -100, 50), false], + ]; + } + + /** + * @dataProvider validateDataProvider + * @param string $phone_no + * @param Location $address + * @param array $expected_errors + */ + public function testValidate(string $phone_no, Location $address, array $expected_errors) + { + $this->dummy_store->setPhoneNo($phone_no); + $this->dummy_store->setAddress($address); - // Test for an invalid phone number (too short) - $this->dummy_store->setPhoneNo('123'); // Short phone number $errors = $this->dummy_store->validate(); - self::assertArrayHasKey('phone_no', $errors); + + $this->assertEquals($expected_errors, $errors); } - public function testGetProductStock(): void + public static function validateDataProvider(): array { - // Assuming product_id 1 is present in the store - $product_id = 1; - $stock_level = $this->dummy_store->getProductStock($product_id); - self::assertGreaterThanOrEqual(0, $stock_level); + return [ + // Valid phone number, valid address (no errors) + ["1234567890", new Location("Royal", "Curepipe", 1, 50, 50), []], + // Invalid phone number (less than 7 characters) + ["123456", new Location("Royal", "Curepipe", 1, 50, 50), ["phone_no" => "Phone number must be at least 7 characters long"]], + // Empty phone number + ["", new Location("Royal", "Curepipe", 1, 50, 50), ["phone_no" => "Phone number must be at least 7 characters long"]], + // Invalid characters in phone number + ["123abc", new Location("Royal", "Curepipe", 1, 50, 50), ["phone_no" => "Phone number must be at least 7 characters long"]], + // Invalid address with invalid latitude/longitude + ["1234567890", new Location("Royal", "Curepipe", 1, -100, 50), ["coordinates" => "Invalid latitude or longitude."]], + ]; } }