diff --git a/Modules/Exercise01/Tests/Feature/Http/Controllers/OrderControllerTest.php b/Modules/Exercise01/Tests/Feature/Http/Controllers/OrderControllerTest.php
new file mode 100644
index 0000000..35bd519
--- /dev/null
+++ b/Modules/Exercise01/Tests/Feature/Http/Controllers/OrderControllerTest.php
@@ -0,0 +1,144 @@
+priceServiceMock = $this->mock(PriceService::class);
+ }
+
+ function test_it_show_form_order()
+ {
+ $url = action([OrderController::class, 'showForm']);
+
+ $response = $this->get($url);
+
+ $response->assertViewIs('exercise01::order');
+ $response->assertViewHasAll([
+ 'unitPrice',
+ 'voucherUnitPrice',
+ 'specialTimeUnitPrice',
+ 'specialTimePeriod',
+ ]);
+ $response->assertSessionMissing('order');
+ }
+
+ private function inValidInputs($inputs)
+ {
+ $validInputs = [
+ 'quantity' => 1,
+ 'voucher' => null,
+ ];
+
+ return array_filter(array_merge($validInputs, $inputs), function ($value) {
+ return $value !== null;
+ });
+ }
+
+ /**
+ * @dataProvider provideWrongQuantity
+ * @dataProvider provideWrongVoucher
+ */
+ function test_it_show_error_when_input_invalid($inputKey, $inputValue)
+ {
+ $url = action([OrderController::class, 'create']);
+ $inputs = $this->inValidInputs([
+ $inputKey => is_callable($inputValue) ? $inputValue() : $inputValue,
+ ]);
+
+ $response = $this->post($url, $inputs);
+
+ $response->assertSessionHasErrors([$inputKey]);
+ }
+
+ function provideWrongQuantity()
+ {
+ return [
+ 'Quantity is required' => ['quantity', null],
+ 'Quantity should be integer' => ['quantity', 1.1],
+ 'Quantity should be greater than 1' => ['quantity', 0],
+ ];
+ }
+
+ function provideWrongVoucher()
+ {
+ return [
+ 'Voucher must exist' => ['voucher', 'this-voucher-not-exist'],
+ 'Voucher must be active' => [
+ 'voucher',
+ function () {
+ Voucher::factory()->inactive()->create(['code' => 'existed-voucher-but-inactive']);
+
+ return 'existed-voucher-but-inactive';
+ },
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideEmptyVoucher
+ */
+ function test_it_should_not_error_when_input_empty_voucher($voucher)
+ {
+ $url = action([OrderController::class, 'create']);
+ $dummyPrice = new Price(100, 0, 0);
+ $this->priceServiceMock
+ ->shouldReceive('calculate')
+ ->andReturn($dummyPrice);
+
+ $response = $this->post($url, [
+ 'quantity' => 1,
+ 'voucher' => $voucher,
+ ]);
+
+ $response->assertSessionDoesntHaveErrors(['voucher']);
+ }
+
+ function provideEmptyVoucher()
+ {
+ return [
+ 'Voucher can be null' => [null],
+ 'Voucher can be empty string' => [''],
+ 'Voucher can be string with spaces only' => [' '],
+ ];
+ }
+
+ function test_it_create_order_when_input_valid_quantity_and_voucher_code()
+ {
+ Voucher::factory()->active()->create(['code' => 'existed-voucher']);
+ $dummyPrice = new Price(100, 0, 0);
+ $this->priceServiceMock
+ ->shouldReceive('calculate')
+ ->andReturn($dummyPrice);
+
+ $url = action([OrderController::class, 'create']);
+
+ $response = $this->post($url, [
+ 'quantity' => 1,
+ 'voucher' => 'existed-voucher',
+ ]);
+
+ $response->assertSessionDoesntHaveErrors(['quantity']);
+ $response->assertSessionDoesntHaveErrors(['voucher']);
+ $response->assertSessionHasInput(['quantity', 'voucher']);
+ $response->assertSessionHas('order', function ($order) {
+ return $order['quantity'] == 1 && $order['price'] instanceof Price;
+ });
+ }
+}
diff --git a/infection.json b/infection.json
index e93241b..8d8b3de 100644
--- a/infection.json
+++ b/infection.json
@@ -1,7 +1,11 @@
{
"source": {
"directories": [
- "Modules/"
+ "Modules/Exercise01/",
+ "Modules/Exercise03/",
+ "Modules/Exercise04/",
+ "Modules/Exercise05/",
+ "Modules/Exercise07/"
],
"excludes": [
"Config",
diff --git a/phpunit.xml b/phpunit.xml
index 77442f0..6be7968 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -6,9 +6,11 @@
>
- ./tests/Unit
- ./tests/Feature
- ./Modules/**/Tests
+ ./Modules/Exercise01/Tests
+ ./Modules/Exercise03/Tests
+ ./Modules/Exercise04/Tests
+ ./Modules/Exercise05/Tests
+ ./Modules/Exercise07/Tests
./Modules/Exercise01/Tests
@@ -43,8 +45,11 @@
- ./app
- ./Modules
+ ./Modules/Exercise01
+ ./Modules/Exercise03
+ ./Modules/Exercise04
+ ./Modules/Exercise05
+ ./Modules/Exercise07
./Modules/**/Config