diff --git a/src/app/Domain.php b/src/app/Domain.php index 810c0bbf..c6b87400 100644 --- a/src/app/Domain.php +++ b/src/app/Domain.php @@ -1,167 +1,167 @@ morphOne('App\Entitlement', 'entitleable'); } /** * Return list of public+active domain names */ public static function getPublicDomains(): array { $where = sprintf('(type & %s) AND (status & %s)', Domain::TYPE_PUBLIC, Domain::STATUS_ACTIVE); return self::whereRaw($where)->get(['namespace'])->map(function ($domain) { return $domain->namespace; })->toArray(); } /** * Returns whether this domain is active. * * @return bool */ public function isActive(): bool { return $this->status & self::STATUS_ACTIVE; } /** * Returns whether this domain is confirmed the ownership of. * * @return bool */ public function isConfirmed(): bool { return $this->status & self::STATUS_CONFIRMED; } /** * Returns whether this domain is deleted. * * @return bool */ public function isDeleted(): bool { return $this->status & self::STATUS_DELETED; } /** * Returns whether this domain is registered with us. * * @return bool */ public function isExternal(): bool { return $this->type & self::TYPE_EXTERNAL; } /** * Returns whether this domain is hosted with us. * * @return bool */ public function isHosted(): bool { return $this->type & self::TYPE_HOSTED; } /** * Returns whether this domain is new. * * @return bool */ public function isNew(): bool { return $this->status & self::STATUS_NEW; } /** * Returns whether this domain is public. * * @return bool */ public function isPublic(): bool { return $this->type & self::TYPE_PUBLIC; } /** * Returns whether this domain is suspended. * * @return bool */ public function isSuspended(): bool { return $this->status & self::STATUS_SUSPENDED; } /** * Domain status mutator * * @throws \Exception */ public function setStatusAttribute($status) { $new_status = 0; $allowed_values = [ self::STATUS_NEW, self::STATUS_ACTIVE, self::STATUS_CONFIRMED, self::STATUS_SUSPENDED, self::STATUS_DELETED, ]; foreach ($allowed_values as $value) { if ($status & $value) { - $new_status &= $value; + $new_status |= $value; $status ^= $value; } } if ($status > 0) { throw new \Exception("Invalid domain status: {$status}"); } $this->attributes['status'] = $new_status; } } diff --git a/src/tests/Feature/Controller/SignupTest.php b/src/tests/Feature/Controller/SignupTest.php index a9e0c5ad..14de0d90 100644 --- a/src/tests/Feature/Controller/SignupTest.php +++ b/src/tests/Feature/Controller/SignupTest.php @@ -1,626 +1,627 @@ "SignupControllerTest1@$domain"]); } /** * {@inheritDoc} * * @return void */ public function tearDown(): void { $domain = self::getPublicDomain(); User::where('email', "signuplogin@$domain") ->orWhere('email', "SignupControllerTest1@$domain") ->orWhere('email', 'admin@external.com') ->delete(); Domain::where('namespace', 'signup-domain.com') ->orWhere('namespace', 'external.com') ->delete(); } /** * Return a public domain for signup tests */ public function getPublicDomain(): string { if (!self::$domain) { $this->refreshApplication(); - self::$domain = Domain::getPublicDomains()[0]; + $public_domains = Domain::getPublicDomains(); + self::$domain = reset($public_domains); if (empty(self::$domain)) { self::$domain = 'signup-domain.com'; Domain::create([ 'namespace' => self::$domain, - 'status' => Domain::STATUS_Active, + 'status' => Domain::STATUS_ACTIVE, 'type' => Domain::TYPE_PUBLIC, ]); } } return self::$domain; } /** * Test fetching plans for signup * * @return void */ public function testSignupPlans() { // Note: this uses plans that already have been seeded into the DB $response = $this->get('/api/auth/signup/plans'); $json = $response->json(); $response->assertStatus(200); $this->assertSame('success', $json['status']); $this->assertCount(2, $json['plans']); $this->assertArrayHasKey('title', $json['plans'][0]); $this->assertArrayHasKey('name', $json['plans'][0]); $this->assertArrayHasKey('description', $json['plans'][0]); $this->assertArrayHasKey('button', $json['plans'][0]); } /** * Test signup initialization with invalid input * * @return void */ public function testSignupInitInvalidInput() { // Empty input data $data = []; $response = $this->post('/api/auth/signup/init', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(2, $json['errors']); $this->assertArrayHasKey('email', $json['errors']); $this->assertArrayHasKey('name', $json['errors']); // Data with missing name $data = [ 'email' => 'UsersApiControllerTest1@UsersApiControllerTest.com', ]; $response = $this->post('/api/auth/signup/init', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); $this->assertArrayHasKey('name', $json['errors']); // Data with invalid email (but not phone number) $data = [ 'email' => '@example.org', 'name' => 'Signup User', ]; $response = $this->post('/api/auth/signup/init', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); $this->assertArrayHasKey('email', $json['errors']); // TODO: Test phone validation } /** * Test signup initialization with valid input * * @return array */ public function testSignupInitValidInput() { Queue::fake(); // Assert that no jobs were pushed... Queue::assertNothingPushed(); $data = [ 'email' => 'testuser@external.com', 'name' => 'Signup User', 'plan' => 'individual', ]; $response = $this->post('/api/auth/signup/init', $data); $json = $response->json(); $response->assertStatus(200); $this->assertCount(2, $json); $this->assertSame('success', $json['status']); $this->assertNotEmpty($json['code']); // Assert the email sending job was pushed once Queue::assertPushed(\App\Jobs\SignupVerificationEmail::class, 1); // Assert the job has proper data assigned Queue::assertPushed(\App\Jobs\SignupVerificationEmail::class, function ($job) use ($data, $json) { // Access protected property $reflection = new \ReflectionClass($job); $code = $reflection->getProperty('code'); $code->setAccessible(true); $code = $code->getValue($job); return $code->code === $json['code'] && $code->data['plan'] === $data['plan'] && $code->data['email'] === $data['email'] && $code->data['name'] === $data['name']; }); return [ 'code' => $json['code'], 'email' => $data['email'], 'name' => $data['name'], 'plan' => $data['plan'], ]; } /** * Test signup code verification with invalid input * * @depends testSignupInitValidInput * @return void */ public function testSignupVerifyInvalidInput(array $result) { // Empty data $data = []; $response = $this->post('/api/auth/signup/verify', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(2, $json['errors']); $this->assertArrayHasKey('code', $json['errors']); $this->assertArrayHasKey('short_code', $json['errors']); // Data with existing code but missing short_code $data = [ 'code' => $result['code'], ]; $response = $this->post('/api/auth/signup/verify', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); $this->assertArrayHasKey('short_code', $json['errors']); // Data with invalid short_code $data = [ 'code' => $result['code'], 'short_code' => 'XXXX', ]; $response = $this->post('/api/auth/signup/verify', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); $this->assertArrayHasKey('short_code', $json['errors']); // TODO: Test expired code } /** * Test signup code verification with valid input * * @depends testSignupInitValidInput * * @return array */ public function testSignupVerifyValidInput(array $result) { $code = SignupCode::find($result['code']); $data = [ 'code' => $code->code, 'short_code' => $code->short_code, ]; $response = $this->post('/api/auth/signup/verify', $data); $json = $response->json(); $response->assertStatus(200); $this->assertCount(5, $json); $this->assertSame('success', $json['status']); $this->assertSame($result['email'], $json['email']); $this->assertSame($result['name'], $json['name']); $this->assertSame(false, $json['is_domain']); $this->assertTrue(is_array($json['domains']) && !empty($json['domains'])); return $result; } /** * Test last signup step with invalid input * * @depends testSignupVerifyValidInput * @return void */ public function testSignupInvalidInput(array $result) { // Empty data $data = []; $response = $this->post('/api/auth/signup', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(3, $json['errors']); $this->assertArrayHasKey('login', $json['errors']); $this->assertArrayHasKey('password', $json['errors']); $this->assertArrayHasKey('domain', $json['errors']); $domain = $this->getPublicDomain(); // Passwords do not match and missing domain $data = [ 'login' => 'test', 'password' => 'test', 'password_confirmation' => 'test2', ]; $response = $this->post('/api/auth/signup', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(2, $json['errors']); $this->assertArrayHasKey('password', $json['errors']); $this->assertArrayHasKey('domain', $json['errors']); $domain = $this->getPublicDomain(); // Login too short $data = [ 'login' => '1', 'domain' => $domain, 'password' => 'test', 'password_confirmation' => 'test', ]; $response = $this->post('/api/auth/signup', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); $this->assertArrayHasKey('login', $json['errors']); // Missing codes $data = [ 'login' => 'login-valid', 'domain' => $domain, 'password' => 'test', 'password_confirmation' => 'test', ]; $response = $this->post('/api/auth/signup', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(2, $json['errors']); $this->assertArrayHasKey('code', $json['errors']); $this->assertArrayHasKey('short_code', $json['errors']); // Data with invalid short_code $data = [ 'login' => 'TestLogin', 'domain' => $domain, 'password' => 'test', 'password_confirmation' => 'test', 'code' => $result['code'], 'short_code' => 'XXXX', ]; $response = $this->post('/api/auth/signup', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); $this->assertArrayHasKey('short_code', $json['errors']); // Valid code, invalid login $code = SignupCode::find($result['code']); $data = [ 'login' => 'żżżżżż', 'domain' => $domain, 'password' => 'test', 'password_confirmation' => 'test', 'code' => $result['code'], 'short_code' => $code->short_code, ]; $response = $this->post('/api/auth/signup', $data); $json = $response->json(); $response->assertStatus(422); $this->assertSame('error', $json['status']); $this->assertCount(1, $json['errors']); $this->assertArrayHasKey('login', $json['errors']); } /** * Test last signup step with valid input (user creation) * * @depends testSignupVerifyValidInput * @return void */ public function testSignupValidInput(array $result) { $domain = $this->getPublicDomain(); $identity = \strtolower('SignupLogin@') . $domain; $code = SignupCode::find($result['code']); $data = [ 'login' => 'SignupLogin', 'domain' => $domain, 'password' => 'test', 'password_confirmation' => 'test', 'code' => $code->code, 'short_code' => $code->short_code, ]; $response = $this->post('/api/auth/signup', $data); $json = $response->json(); $response->assertStatus(200); $this->assertCount(4, $json); $this->assertSame('success', $json['status']); $this->assertSame('bearer', $json['token_type']); $this->assertTrue(!empty($json['expires_in']) && is_int($json['expires_in']) && $json['expires_in'] > 0); $this->assertNotEmpty($json['access_token']); // Check if the code has been removed $this->assertNull(SignupCode::where($result['code'])->first()); // Check if the user has been created $user = User::where('email', $identity)->first(); $this->assertNotEmpty($user); $this->assertSame($identity, $user->email); $this->assertSame($result['name'], $user->name); // Check external email in user settings $this->assertSame($result['email'], $user->getSetting('external_email')); // TODO: Check SKUs/Plan // TODO: Check if the access token works } /** * Test signup for a group (custom domain) account * * @return void */ public function testSignupGroupAccount() { Queue::fake(); // Initial signup request $user_data = $data = [ 'email' => 'testuser@external.com', 'name' => 'Signup User', 'plan' => 'group', ]; $response = $this->post('/api/auth/signup/init', $data); $json = $response->json(); $response->assertStatus(200); $this->assertCount(2, $json); $this->assertSame('success', $json['status']); $this->assertNotEmpty($json['code']); // Assert the email sending job was pushed once Queue::assertPushed(\App\Jobs\SignupVerificationEmail::class, 1); // Assert the job has proper data assigned Queue::assertPushed(\App\Jobs\SignupVerificationEmail::class, function ($job) use ($data, $json) { // Access protected property $reflection = new \ReflectionClass($job); $code = $reflection->getProperty('code'); $code->setAccessible(true); $code = $code->getValue($job); return $code->code === $json['code'] && $code->data['plan'] === $data['plan'] && $code->data['email'] === $data['email'] && $code->data['name'] === $data['name']; }); // Verify the code $code = SignupCode::find($json['code']); $data = [ 'code' => $code->code, 'short_code' => $code->short_code, ]; $response = $this->post('/api/auth/signup/verify', $data); $result = $response->json(); $response->assertStatus(200); $this->assertCount(5, $result); $this->assertSame('success', $result['status']); $this->assertSame($user_data['email'], $result['email']); $this->assertSame($user_data['name'], $result['name']); $this->assertSame(true, $result['is_domain']); $this->assertSame([], $result['domains']); // Final signup request $login = 'admin'; $domain = 'external.com'; $data = [ 'login' => $login, 'domain' => $domain, 'password' => 'test', 'password_confirmation' => 'test', 'code' => $code->code, 'short_code' => $code->short_code, ]; $response = $this->post('/api/auth/signup', $data); $result = $response->json(); $response->assertStatus(200); $this->assertCount(4, $result); $this->assertSame('success', $result['status']); $this->assertSame('bearer', $result['token_type']); $this->assertTrue(!empty($result['expires_in']) && is_int($result['expires_in']) && $result['expires_in'] > 0); $this->assertNotEmpty($result['access_token']); // Check if the code has been removed $this->assertNull(SignupCode::find($code->id)); // Check if the user has been created $user = User::where('email', $login . '@' . $domain)->first(); $this->assertNotEmpty($user); $this->assertSame($user_data['name'], $user->name); // Check domain record // Check external email in user settings $this->assertSame($user_data['email'], $user->getSetting('external_email')); // TODO: Check SKUs/Plan // TODO: Check if the access token works } /** * List of email address validation cases for testValidateEmail() * * @return array Arguments for testValidateEmail() */ public function dataValidateEmail() { return [ // invalid ['', 'validation.emailinvalid'], ['example.org', 'validation.emailinvalid'], ['@example.org', 'validation.emailinvalid'], ['test@localhost', 'validation.emailinvalid'], // valid ['test@domain.tld', null], ['&@example.org', null], ]; } /** * Signup email validation. * * Note: Technicly these are unit tests, but let's keep it here for now. * FIXME: Shall we do a http request for each case? * * @dataProvider dataValidateEmail */ public function testValidateEmail($email, $expected_result) { $method = new \ReflectionMethod('App\Http\Controllers\API\SignupController', 'validateEmail'); $method->setAccessible(true); $result = $method->invoke(new SignupController(), $email); $this->assertSame($expected_result, $result); } /** * List of login/domain validation cases for testValidateLogin() * * @return array Arguments for testValidateLogin() */ public function dataValidateLogin() { $domain = $this->getPublicDomain(); return [ // Individual account ['', $domain, false, ['login' => 'validation.logininvalid']], ['test123456', 'localhost', false, ['domain' => 'validation.domaininvalid']], ['test123456', 'unknown-domain.org', false, ['domain' => 'validation.domaininvalid']], ['test.test', $domain, false, null], ['test_test', $domain, false, null], ['test-test', $domain, false, null], ['admin', $domain, false, ['login' => 'validation.loginexists']], ['administrator', $domain, false, ['login' => 'validation.loginexists']], ['sales', $domain, false, ['login' => 'validation.loginexists']], ['root', $domain, false, ['login' => 'validation.loginexists']], // existing user ['SignupControllerTest1', $domain, false, ['login' => 'validation.loginexists']], // Domain account ['admin', 'kolabsys.com', true, null], ['testnonsystemdomain', 'invalid', true, ['domain' => 'validation.domaininvalid']], ['testnonsystemdomain', '.com', true, ['domain' => 'validation.domaininvalid']], // existing user ['SignupControllerTest1', $domain, true, ['domain' => 'validation.domainexists']], ]; } /** * Signup login/domain validation. * * Note: Technicly these include unit tests, but let's keep it here for now. * FIXME: Shall we do a http request for each case? * * @dataProvider dataValidateLogin */ public function testValidateLogin($login, $domain, $external, $expected_result) { $method = new \ReflectionMethod('App\Http\Controllers\API\SignupController', 'validateLogin'); $method->setAccessible(true); $result = $method->invoke(new SignupController(), $login, $domain, $external); $this->assertSame($expected_result, $result); } } diff --git a/src/tests/Feature/DomainTest.php b/src/tests/Feature/DomainTest.php index 788941f9..5cc5892f 100644 --- a/src/tests/Feature/DomainTest.php +++ b/src/tests/Feature/DomainTest.php @@ -1,101 +1,49 @@ delete(); - } - Domain::where('namespace', 'public-active.com')->delete(); } - public function testDomainStatus(): void - { - $statuses = [ "new", "active", "confirmed", "suspended", "deleted" ]; - - $domains = \App\Utils::powerSet($statuses); - - foreach ($domains as $namespace_elements) { - $namespace = implode('-', $namespace_elements) . '.com'; - - $status = 1; - - if (in_array("new", $namespace_elements)) { - $status += Domain::STATUS_NEW; - } - - if (in_array("active", $namespace_elements)) { - $status += Domain::STATUS_ACTIVE; - } - - if (in_array("confirmed", $namespace_elements)) { - $status += Domain::STATUS_CONFIRMED; - } - - if (in_array("suspended", $namespace_elements)) { - $status += Domain::STATUS_SUSPENDED; - } - - if (in_array("deleted", $namespace_elements)) { - $status += Domain::STATUS_DELETED; - } - - $domain = Domain::firstOrCreate( - [ - 'namespace' => $namespace, - 'status' => $status, - 'type' => Domain::TYPE_EXTERNAL - ] - ); - - $this->assertTrue($domain->status > 1); - } - } - /** * Tests getPublicDomains() method */ public function testGetPublicDomains(): void { $public_domains = Domain::getPublicDomains(); $this->assertNotContains('public-active.com', $public_domains); Domain::create([ 'namespace' => 'public-active.com', 'status' => Domain::STATUS_NEW, 'type' => Domain::TYPE_PUBLIC, ]); // Public but non-active domain should not be returned $public_domains = Domain::getPublicDomains(); $this->assertNotContains('public-active.com', $public_domains); $domain = Domain::where('namespace', 'public-active.com')->first(); $domain->status = Domain::STATUS_ACTIVE; $domain->save(); // Public and active domain should be returned $public_domains = Domain::getPublicDomains(); $this->assertContains('public-active.com', $public_domains); } } diff --git a/src/tests/Feature/EntitlementTest.php b/src/tests/Feature/EntitlementTest.php index 2b4bc164..c4e602ec 100644 --- a/src/tests/Feature/EntitlementTest.php +++ b/src/tests/Feature/EntitlementTest.php @@ -1,90 +1,92 @@ orWhere('email', 'entitled-user@custom-domain.com') ->delete(); } /** * Tests for User::AddEntitlement() */ public function testUserAddEntitlement(): void { $sku_domain = Sku::firstOrCreate(['title' => 'domain']); $sku_mailbox = Sku::firstOrCreate(['title' => 'mailbox']); $owner = User::firstOrCreate(['email' => 'entitlement-test@kolabnow.com']); $user = User::firstOrCreate(['email' => 'entitled-user@custom-domain.com']); $this->assertTrue($owner->id != $user->id); $wallets = $owner->wallets()->get(); $domain = Domain::firstOrCreate( [ - 'namespace' => 'custom-domain.com', + 'namespace' => 'custom-domain.com' + ], + [ 'status' => Domain::STATUS_NEW, 'type' => Domain::TYPE_EXTERNAL, ] ); $entitlement_own_mailbox = new Entitlement( [ 'owner_id' => $owner->id, 'entitleable_id' => $owner->id, 'entitleable_type' => User::class, 'wallet_id' => $wallets[0]->id, 'sku_id' => $sku_mailbox->id, 'description' => "Owner Mailbox Entitlement Test" ] ); $entitlement_domain = new Entitlement( [ 'owner_id' => $owner->id, 'entitleable_id' => $domain->id, 'entitleable_type' => Domain::class, 'wallet_id' => $wallets[0]->id, 'sku_id' => $sku_domain->id, 'description' => "User Domain Entitlement Test" ] ); $entitlement_mailbox = new Entitlement( [ 'owner_id' => $owner->id, 'entitleable_id' => $user->id, 'entitleable_type' => User::class, 'wallet_id' => $wallets[0]->id, 'sku_id' => $sku_mailbox->id, 'description' => "User Mailbox Entitlement Test" ] ); $owner->addEntitlement($entitlement_own_mailbox); $owner->addEntitlement($entitlement_domain); $owner->addEntitlement($entitlement_mailbox); $this->assertTrue($owner->entitlements()->count() == 3); $this->assertTrue($sku_domain->entitlements()->where('owner_id', $owner->id)->count() == 1); $this->assertTrue($sku_mailbox->entitlements()->where('owner_id', $owner->id)->count() == 2); $this->assertTrue($wallets[0]->entitlements()->count() == 3); $this->assertTrue($wallets[0]->fresh()->balance < 0.00); // TODO: Test case of adding entitlement that already exists } } diff --git a/src/tests/Feature/SkuTest.php b/src/tests/Feature/SkuTest.php index 5a47fdcc..f6301873 100644 --- a/src/tests/Feature/SkuTest.php +++ b/src/tests/Feature/SkuTest.php @@ -1,165 +1,167 @@ 'custom-domain.com', + 'namespace' => 'custom-domain.com' + ], + [ 'status' => Domain::STATUS_NEW, 'type' => Domain::TYPE_EXTERNAL, ] ); User::firstOrCreate( ['email' => 'sku-test-user@custom-domain.com'] ); } public function tearDown(): void { User::where('email', 'sku-test-user@custom-domain.com')->delete(); Domain::where('namespace', 'custom-domain.com')->delete(); } /** * Tests for Sku::registerEntitlements() */ public function testRegisterEntitlement(): void { // TODO: This test depends on seeded SKUs, but probably should not $user = User::where('email', 'sku-test-user@custom-domain.com')->first(); $domain = Domain::where('namespace', 'custom-domain.com')->first(); $wallet = $user->wallets()->first(); // \App\Handlers\Mailbox SKU // Note, we're testing mailbox SKU before domain SKU as it may potentially fail in that order $sku = Sku::where('title', 'mailbox')->first(); $sku->registerEntitlement($user); $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get(); $wallet->refresh(); if ($sku->active) { $balance = -$sku->cost; $this->assertCount(1, $entitlements); $this->assertSame($user->id, $entitlements[0]->entitleable_id); $this->assertSame(Handlers\Mailbox::entitleableClass(), $entitlements[0]->entitleable_type); } else { $this->assertCount(0, $entitlements); } $this->assertEquals($balance, $wallet->balance); // \App\Handlers\Domain SKU $sku = Sku::where('title', 'domain')->first(); $sku->registerEntitlement($user, [$domain]); $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get(); $wallet->refresh(); if ($sku->active) { $balance -= $sku->cost; $this->assertCount(1, $entitlements); $this->assertSame($domain->id, $entitlements[0]->entitleable_id); $this->assertSame(Handlers\Domain::entitleableClass(), $entitlements[0]->entitleable_type); } else { $this->assertCount(0, $entitlements); } $this->assertEquals($balance, $wallet->balance); // \App\Handlers\DomainRegistration SKU $sku = Sku::where('title', 'domain-registration')->first(); $sku->registerEntitlement($user, [$domain]); $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get(); $wallet->refresh(); if ($sku->active) { $balance -= $sku->cost; $this->assertCount(1, $entitlements); $this->assertSame($domain->id, $entitlements[0]->entitleable_id); $this->assertSame(Handlers\DomainRegistration::entitleableClass(), $entitlements[0]->entitleable_type); } else { $this->assertCount(0, $entitlements); } $this->assertEquals($balance, $wallet->balance); // \App\Handlers\DomainHosting SKU $sku = Sku::where('title', 'domain-hosting')->first(); $sku->registerEntitlement($user, [$domain]); $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get(); $wallet->refresh(); if ($sku->active) { $balance -= $sku->cost; $this->assertCount(1, $entitlements); $this->assertSame($domain->id, $entitlements[0]->entitleable_id); $this->assertSame(Handlers\DomainHosting::entitleableClass(), $entitlements[0]->entitleable_type); } else { $this->assertCount(0, $entitlements); } $this->assertEquals($balance, $wallet->balance); // \App\Handlers\Groupware SKU $sku = Sku::where('title', 'groupware')->first(); $sku->registerEntitlement($user, [$domain]); $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get(); $wallet->refresh(); if ($sku->active) { $balance -= $sku->cost; $this->assertCount(1, $entitlements); $this->assertSame($user->id, $entitlements[0]->entitleable_id); $this->assertSame(Handlers\Mailbox::entitleableClass(), $entitlements[0]->entitleable_type); } else { $this->assertCount(0, $entitlements); } $this->assertEquals($balance, $wallet->balance); // \App\Handlers\Storage SKU $sku = Sku::where('title', 'storage')->first(); $sku->registerEntitlement($user, [$domain]); $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get(); $wallet->refresh(); if ($sku->active) { $balance -= $sku->cost; // For Storage entitlement we expect additional Quota record $quota = Quota::where('user_id', $user->id)->first(); $this->assertTrue(!empty($quota)); // TODO: This should be a constant and/or config option, and probably // quota should not be in bytes $this->assertSame(2147483648, $quota->value); $this->assertCount(1, $entitlements); $this->assertSame($quota->id, $entitlements[0]->entitleable_id); $this->assertSame(Handlers\Storage::entitleableClass(), $entitlements[0]->entitleable_type); } else { $this->assertCount(0, $entitlements); } $this->assertEquals($balance, $wallet->balance); } } diff --git a/src/tests/Feature/UserTest.php b/src/tests/Feature/UserTest.php index 574775eb..4fc4ba40 100644 --- a/src/tests/Feature/UserTest.php +++ b/src/tests/Feature/UserTest.php @@ -1,66 +1,66 @@ 'UserAccountA@UserAccount.com']); $this->assertTrue($userA->wallets()->count() == 1); $userA->wallets()->each( function ($wallet) { $userB = User::firstOrCreate(['email' => 'UserAccountB@UserAccount.com']); $wallet->addController($userB); } ); $userB = User::firstOrCreate(['email' => 'UserAccountB@UserAccount.com']); $this->assertTrue($userB->accounts()->get()[0]->id === $userA->wallets()->get()[0]->id); } public function testUserDomains(): void { $user = User::firstOrCreate(['email' => 'john@kolab.org']); $domains = []; foreach ($user->domains() as $domain) { $domains[] = $domain->namespace; } - $this->assertTrue(in_array('kolabnow.com', $domains)); - $this->assertTrue(in_array('kolab.org', $domains)); + $this->assertContains('kolabnow.com', $domains); + $this->assertContains('kolab.org', $domains); } /** * Tests for User::findByEmail() */ public function testFindByEmail(): void { $user = User::firstOrCreate(['email' => 'john@kolab.org']); $result = User::findByEmail('john'); $this->assertNull($result); $result = User::findByEmail('non-existing@email.com'); $this->assertNull($result); $result = User::findByEmail('john@kolab.org'); $this->assertInstanceOf(User::class, $result); $this->assertSame($user->id, $result->id); // TODO: Make sure searching is case-insensitive // TODO: Alias, eternal email } }