makeShop('pr'); ShopCustomer::create([ 'name' => 'X', 'phone' => '+37377000001', 'email' => 'x@example.com', 'password' => Hash::make('old'), ]); Mail::fake(); $this->post('http://pr.service.mir.md/shop/password/email', [ 'email' => 'x@example.com', ])->assertSessionHas('status'); Mail::assertSent(ShopPasswordResetMail::class, fn ($m) => $m->customer->email === 'x@example.com'); } public function test_forgot_does_not_disclose_unknown_email(): void { $this->makeShop('pru'); Mail::fake(); $this->post('http://pru.service.mir.md/shop/password/email', [ 'email' => 'ghost@example.com', ])->assertSessionHas('status'); // same generic status, no error Mail::assertNothingSent(); } public function test_reset_with_valid_token_changes_password(): void { $this->makeShop('rs'); $cust = ShopCustomer::create([ 'name' => 'R', 'phone' => '+37377000002', 'email' => 'r@example.com', 'password' => Hash::make('old'), ]); $token = Password::broker('shop_customers')->createToken($cust); $this->post('http://rs.service.mir.md/shop/password/reset', [ 'token' => $token, 'email' => 'r@example.com', 'password' => 'newpassword', 'password_confirmation' => 'newpassword', ])->assertRedirect('/shop/login'); $cust->refresh(); $this->assertTrue(Hash::check('newpassword', $cust->password)); } public function test_reset_with_bad_token_rejected(): void { $this->makeShop('bad'); ShopCustomer::create([ 'name' => 'B', 'phone' => '+37377000003', 'email' => 'b@example.com', 'password' => Hash::make('old'), ]); $this->post('http://bad.service.mir.md/shop/password/reset', [ 'token' => 'not-a-real-token', 'email' => 'b@example.com', 'password' => 'newpassword', 'password_confirmation' => 'newpassword', ])->assertSessionHasErrors(); } public function test_order_notifier_sends_email_when_customer_email_present(): void { $ctx = $this->makeShop('mail'); Mail::fake(); $order = OnlineOrder::create([ 'number' => OnlineOrder::generateNumber($ctx->id), 'customer_name' => 'M', 'customer_phone' => '+37377000004', 'customer_email' => 'm@example.com', 'delivery_method' => 'pickup', 'status' => 'new', ]); app(ShopOrderNotifier::class)->placed($order); Mail::assertSent(ShopOrderConfirmationMail::class, fn ($m) => $m->order->id === $order->id); } public function test_order_notifier_skips_email_without_customer_email(): void { $ctx = $this->makeShop('noeml'); Mail::fake(); $order = OnlineOrder::create([ 'number' => OnlineOrder::generateNumber($ctx->id), 'customer_name' => 'N', 'customer_phone' => '+37377000005', 'delivery_method' => 'pickup', 'status' => 'new', ]); app(ShopOrderNotifier::class)->placed($order); Mail::assertNotSent(ShopOrderConfirmationMail::class); } public function test_part_has_multiple_images_collection(): void { $this->makeShop('multi'); $part = \App\Models\Tenant\Part::create([ 'name' => 'P', 'sell_price' => 10, 'qty' => 1, 'unit' => 'buc', 'is_active' => true, 'buy_price' => 5, ]); $this->assertIsArray($part->imageUrls()); $this->assertCount(0, $part->imageUrls()); } private function makeShop(string $slug): Company { $plan = Plan::firstOrCreate(['slug' => 'test'], ['name' => 'T', 'price' => 0, 'features' => []]); $company = Company::create([ 'plan_id' => $plan->id, 'slug' => $slug, 'name' => ucfirst($slug), 'status' => 'active', 'settings' => ['shop' => ['enabled' => true, 'delivery_methods' => ['pickup']]], ]); app(TenantManager::class)->setCurrent($company); return $company; } }