Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Browser/Admin/UserTest.php
Show All 27 Lines | public function setUp(): void | ||||
'phone' => '+48123123123', | 'phone' => '+48123123123', | ||||
'external_email' => 'john.doe.external@gmail.com', | 'external_email' => 'john.doe.external@gmail.com', | ||||
]); | ]); | ||||
if ($john->isSuspended()) { | if ($john->isSuspended()) { | ||||
User::where('email', $john->email)->update(['status' => $john->status - User::STATUS_SUSPENDED]); | User::where('email', $john->email)->update(['status' => $john->status - User::STATUS_SUSPENDED]); | ||||
} | } | ||||
$wallet = $john->wallets()->first(); | $wallet = $john->wallets()->first(); | ||||
$wallet->discount()->dissociate(); | $wallet->discount()->dissociate(); | ||||
$wallet->balance = 0; | |||||
$wallet->save(); | |||||
} | } | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
public function tearDown(): void | public function tearDown(): void | ||||
{ | { | ||||
$john = $this->getTestUser('john@kolab.org'); | $john = $this->getTestUser('john@kolab.org'); | ||||
$john->setSettings([ | $john->setSettings([ | ||||
'phone' => null, | 'phone' => null, | ||||
'external_email' => 'john.doe.external@gmail.com', | 'external_email' => 'john.doe.external@gmail.com', | ||||
]); | ]); | ||||
if ($john->isSuspended()) { | if ($john->isSuspended()) { | ||||
User::where('email', $john->email)->update(['status' => $john->status - User::STATUS_SUSPENDED]); | User::where('email', $john->email)->update(['status' => $john->status - User::STATUS_SUSPENDED]); | ||||
} | } | ||||
$wallet = $john->wallets()->first(); | $wallet = $john->wallets()->first(); | ||||
$wallet->discount()->dissociate(); | $wallet->discount()->dissociate(); | ||||
$wallet->balance = 0; | |||||
$wallet->save(); | |||||
parent::tearDown(); | parent::tearDown(); | ||||
} | } | ||||
/** | /** | ||||
* Test user info page (unauthenticated) | * Test user info page (unauthenticated) | ||||
*/ | */ | ||||
public function testUserUnauth(): void | public function testUserUnauth(): void | ||||
Show All 39 Lines | public function testUserInfo(): void | ||||
->assertSeeIn('.row:nth-child(7) label', 'Country') | ->assertSeeIn('.row:nth-child(7) label', 'Country') | ||||
->assertSeeIn('.row:nth-child(7) #country', 'United States of America'); | ->assertSeeIn('.row:nth-child(7) #country', 'United States of America'); | ||||
}); | }); | ||||
// Some tabs are loaded in background, wait a second | // Some tabs are loaded in background, wait a second | ||||
$browser->pause(500) | $browser->pause(500) | ||||
->assertElementsCount('@nav a', 5); | ->assertElementsCount('@nav a', 5); | ||||
// Assert Finances tab | // Note: Finances tab is tested in UserFinancesTest.php | ||||
$browser->assertSeeIn('@nav #tab-finances', 'Finances') | $browser->assertSeeIn('@nav #tab-finances', 'Finances'); | ||||
->with('@user-finances', function (Browser $browser) { | |||||
$browser->waitUntilMissing('.app-loader') | |||||
->assertSeeIn('.card-title', 'Account balance') | |||||
->assertSeeIn('.card-title .text-success', '0,00 CHF') | |||||
->with('form', function (Browser $browser) { | |||||
$payment_provider = ucfirst(\config('services.payment_provider')); | |||||
$browser->assertElementsCount('.row', 2) | |||||
->assertSeeIn('.row:nth-child(1) label', 'Discount') | |||||
->assertSeeIn('.row:nth-child(1) #discount span', 'none') | |||||
->assertSeeIn('.row:nth-child(2) label', $payment_provider . ' ID') | |||||
->assertVisible('.row:nth-child(2) a'); | |||||
}); | |||||
}); | |||||
// Assert Aliases tab | // Assert Aliases tab | ||||
$browser->assertSeeIn('@nav #tab-aliases', 'Aliases (1)') | $browser->assertSeeIn('@nav #tab-aliases', 'Aliases (1)') | ||||
->click('@nav #tab-aliases') | ->click('@nav #tab-aliases') | ||||
->whenAvailable('@user-aliases', function (Browser $browser) { | ->whenAvailable('@user-aliases', function (Browser $browser) { | ||||
$browser->assertElementsCount('table tbody tr', 1) | $browser->assertElementsCount('table tbody tr', 1) | ||||
->assertSeeIn('table tbody tr:first-child td:first-child', 'jack.daniels@kolab.org') | ->assertSeeIn('table tbody tr:first-child td:first-child', 'jack.daniels@kolab.org') | ||||
->assertMissing('table tfoot'); | ->assertMissing('table tfoot'); | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | public function testUserInfo2(): void | ||||
->assertSeeIn('.row:nth-child(9) label', 'Country') | ->assertSeeIn('.row:nth-child(9) label', 'Country') | ||||
->assertSeeIn('.row:nth-child(9) #country', 'United States of America'); | ->assertSeeIn('.row:nth-child(9) #country', 'United States of America'); | ||||
}); | }); | ||||
// Some tabs are loaded in background, wait a second | // Some tabs are loaded in background, wait a second | ||||
$browser->pause(500) | $browser->pause(500) | ||||
->assertElementsCount('@nav a', 5); | ->assertElementsCount('@nav a', 5); | ||||
// Assert Finances tab | // Note: Finances tab is tested in UserFinancesTest.php | ||||
$browser->assertSeeIn('@nav #tab-finances', 'Finances') | $browser->assertSeeIn('@nav #tab-finances', 'Finances'); | ||||
->with('@user-finances', function (Browser $browser) { | |||||
$browser->waitUntilMissing('.app-loader') | |||||
->assertSeeIn('.card-title', 'Account balance') | |||||
->assertSeeIn('.card-title .text-danger', '-20,10 CHF') | |||||
->with('form', function (Browser $browser) { | |||||
$browser->assertElementsCount('.row', 2) | |||||
->assertSeeIn('.row:nth-child(1) label', 'Discount') | |||||
->assertSeeIn('.row:nth-child(1) #discount span', '10% - Test voucher'); | |||||
}); | |||||
}); | |||||
// Assert Aliases tab | // Assert Aliases tab | ||||
$browser->assertSeeIn('@nav #tab-aliases', 'Aliases (1)') | $browser->assertSeeIn('@nav #tab-aliases', 'Aliases (1)') | ||||
->click('@nav #tab-aliases') | ->click('@nav #tab-aliases') | ||||
->whenAvailable('@user-aliases', function (Browser $browser) { | ->whenAvailable('@user-aliases', function (Browser $browser) { | ||||
$browser->assertElementsCount('table tbody tr', 1) | $browser->assertElementsCount('table tbody tr', 1) | ||||
->assertSeeIn('table tbody tr:first-child td:first-child', 'john.doe@kolab.org') | ->assertSeeIn('table tbody tr:first-child td:first-child', 'john.doe@kolab.org') | ||||
->assertMissing('table tfoot'); | ->assertMissing('table tfoot'); | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | public function testUserInfo2(): void | ||||
$browser->assertSeeIn('.row:nth-child(2) label', 'ID (Created at)') | $browser->assertSeeIn('.row:nth-child(2) label', 'ID (Created at)') | ||||
->assertSeeIn('.row:nth-child(2) #userid', "{$ned->id} ({$ned->created_at})"); | ->assertSeeIn('.row:nth-child(2) #userid', "{$ned->id} ({$ned->created_at})"); | ||||
}); | }); | ||||
// Some tabs are loaded in background, wait a second | // Some tabs are loaded in background, wait a second | ||||
$browser->pause(500) | $browser->pause(500) | ||||
->assertElementsCount('@nav a', 5); | ->assertElementsCount('@nav a', 5); | ||||
// Assert Finances tab | // Note: Finances tab is tested in UserFinancesTest.php | ||||
$browser->assertSeeIn('@nav #tab-finances', 'Finances') | $browser->assertSeeIn('@nav #tab-finances', 'Finances'); | ||||
->with('@user-finances', function (Browser $browser) { | |||||
$browser->waitUntilMissing('.app-loader') | |||||
->assertSeeIn('.card-title', 'Account balance') | |||||
->assertSeeIn('.card-title .text-success', '0,00 CHF') | |||||
->with('form', function (Browser $browser) { | |||||
$browser->assertElementsCount('.row', 2) | |||||
->assertSeeIn('.row:nth-child(1) label', 'Discount') | |||||
->assertSeeIn('.row:nth-child(1) #discount span', 'none'); | |||||
}); | |||||
}); | |||||
// Assert Aliases tab | // Assert Aliases tab | ||||
$browser->assertSeeIn('@nav #tab-aliases', 'Aliases (0)') | $browser->assertSeeIn('@nav #tab-aliases', 'Aliases (0)') | ||||
->click('@nav #tab-aliases') | ->click('@nav #tab-aliases') | ||||
->whenAvailable('@user-aliases', function (Browser $browser) { | ->whenAvailable('@user-aliases', function (Browser $browser) { | ||||
$browser->assertElementsCount('table tbody tr', 0) | $browser->assertElementsCount('table tbody tr', 0) | ||||
->assertSeeIn('table tfoot tr td', 'This user has no email aliases.'); | ->assertSeeIn('table tfoot tr td', 'This user has no email aliases.'); | ||||
}); | }); | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | public function testSuspendAndUnsuspend(): void | ||||
->assertMissing('@user-info #button-suspend') | ->assertMissing('@user-info #button-suspend') | ||||
->click('@user-info #button-unsuspend') | ->click('@user-info #button-unsuspend') | ||||
->assertToast(Toast::TYPE_SUCCESS, 'User unsuspended successfully.') | ->assertToast(Toast::TYPE_SUCCESS, 'User unsuspended successfully.') | ||||
->assertSeeIn('@user-info #status span.text-success', 'Active') | ->assertSeeIn('@user-info #status span.text-success', 'Active') | ||||
->assertVisible('@user-info #button-suspend') | ->assertVisible('@user-info #button-suspend') | ||||
->assertMissing('@user-info #button-unsuspend'); | ->assertMissing('@user-info #button-unsuspend'); | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* Test editing wallet discount | |||||
* | |||||
* @depends testUserInfo2 | |||||
*/ | |||||
public function testWalletDiscount(): void | |||||
{ | |||||
$this->browse(function (Browser $browser) { | |||||
$john = $this->getTestUser('john@kolab.org'); | |||||
$browser->visit(new UserPage($john->id)) | |||||
->pause(100) | |||||
->waitUntilMissing('@user-finances .app-loader') | |||||
->click('@user-finances #discount button') | |||||
// Test dialog content, and closing it with Cancel button | |||||
->with(new Dialog('#discount-dialog'), function (Browser $browser) { | |||||
$browser->assertSeeIn('@title', 'Account discount') | |||||
->assertFocused('@body select') | |||||
->assertSelected('@body select', '') | |||||
->assertSeeIn('@button-cancel', 'Cancel') | |||||
->assertSeeIn('@button-action', 'Submit') | |||||
->click('@button-cancel'); | |||||
}) | |||||
->assertMissing('#discount-dialog') | |||||
->click('@user-finances #discount button') | |||||
// Change the discount | |||||
->with(new Dialog('#discount-dialog'), function (Browser $browser) { | |||||
$browser->click('@body select') | |||||
->click('@body select option:nth-child(2)') | |||||
->click('@button-action'); | |||||
}) | |||||
->assertToast(Toast::TYPE_SUCCESS, 'User wallet updated successfully.') | |||||
->assertSeeIn('#discount span', '10% - Test voucher') | |||||
->click('@nav #tab-subscriptions') | |||||
->with('@user-subscriptions', function (Browser $browser) { | |||||
$browser->assertSeeIn('table tbody tr:nth-child(1) td:last-child', '3,99 CHF/month¹') | |||||
->assertSeeIn('table tbody tr:nth-child(2) td:last-child', '0,00 CHF/month¹') | |||||
->assertSeeIn('table tbody tr:nth-child(3) td:last-child', '4,99 CHF/month¹') | |||||
->assertSeeIn('table + .hint', '¹ applied discount: 10% - Test voucher'); | |||||
}) | |||||
// Change back to 'none' | |||||
->click('@nav #tab-finances') | |||||
->click('@user-finances #discount button') | |||||
->with(new Dialog('#discount-dialog'), function (Browser $browser) { | |||||
$browser->click('@body select') | |||||
->click('@body select option:nth-child(1)') | |||||
->click('@button-action'); | |||||
}) | |||||
->assertToast(Toast::TYPE_SUCCESS, 'User wallet updated successfully.') | |||||
->assertSeeIn('#discount span', 'none') | |||||
->click('@nav #tab-subscriptions') | |||||
->with('@user-subscriptions', function (Browser $browser) { | |||||
$browser->assertSeeIn('table tbody tr:nth-child(1) td:last-child', '4,44 CHF/month') | |||||
->assertSeeIn('table tbody tr:nth-child(2) td:last-child', '0,00 CHF/month') | |||||
->assertSeeIn('table tbody tr:nth-child(3) td:last-child', '5,55 CHF/month') | |||||
->assertMissing('table + .hint'); | |||||
}); | |||||
}); | |||||
} | |||||
/** | |||||
* Test awarding/penalizing a wallet | |||||
*/ | |||||
public function testBonusPenalty(): void | |||||
{ | |||||
$this->browse(function (Browser $browser) { | |||||
$john = $this->getTestUser('john@kolab.org'); | |||||
$browser->visit(new UserPage($john->id)) | |||||
->waitFor('@user-finances #button-award') | |||||
->click('@user-finances #button-award') | |||||
// Test dialog content, and closing it with Cancel button | |||||
->with(new Dialog('#oneoff-dialog'), function (Browser $browser) { | |||||
$browser->assertSeeIn('@title', 'Add a bonus to the wallet') | |||||
->assertFocused('@body input#oneoff_amount') | |||||
->assertSeeIn('@body label[for="oneoff_amount"]', 'Amount') | |||||
->assertvalue('@body input#oneoff_amount', '') | |||||
->assertSeeIn('@body label[for="oneoff_description"]', 'Description') | |||||
->assertvalue('@body input#oneoff_description', '') | |||||
->assertSeeIn('@button-cancel', 'Cancel') | |||||
->assertSeeIn('@button-action', 'Submit') | |||||
->click('@button-cancel'); | |||||
}) | |||||
->assertMissing('#oneoff-dialog'); | |||||
// Test bonus | |||||
$browser->click('@user-finances #button-award') | |||||
->with(new Dialog('#oneoff-dialog'), function (Browser $browser) { | |||||
// Test input validation for a bonus | |||||
$browser->type('@body #oneoff_amount', 'aaa') | |||||
->type('@body #oneoff_description', '') | |||||
->click('@button-action') | |||||
->assertToast(Toast::TYPE_ERROR, 'Form validation error') | |||||
->assertVisible('@body #oneoff_amount.is-invalid') | |||||
->assertVisible('@body #oneoff_description.is-invalid') | |||||
->assertSeeIn( | |||||
'@body #oneoff_amount + span + .invalid-feedback', | |||||
'The amount must be a number.' | |||||
) | |||||
->assertSeeIn( | |||||
'@body #oneoff_description + .invalid-feedback', | |||||
'The description field is required.' | |||||
); | |||||
// Test adding a bonus | |||||
$browser->type('@body #oneoff_amount', '12.34') | |||||
->type('@body #oneoff_description', 'Test bonus') | |||||
->click('@button-action') | |||||
->assertToast(Toast::TYPE_SUCCESS, 'The bonus has been added to the wallet successfully.'); | |||||
}) | |||||
->assertMissing('#oneoff-dialog') | |||||
->assertSeeIn('@user-finances .card-title span.text-success', '12,34 CHF'); | |||||
$this->assertSame(1234, $john->wallets()->first()->balance); | |||||
// Test penalty | |||||
$browser->click('@user-finances #button-penalty') | |||||
// Test dialog content, and closing it with Cancel button | |||||
->with(new Dialog('#oneoff-dialog'), function (Browser $browser) { | |||||
$browser->assertSeeIn('@title', 'Add a penalty to the wallet') | |||||
->assertFocused('@body input#oneoff_amount') | |||||
->assertSeeIn('@body label[for="oneoff_amount"]', 'Amount') | |||||
->assertvalue('@body input#oneoff_amount', '') | |||||
->assertSeeIn('@body label[for="oneoff_description"]', 'Description') | |||||
->assertvalue('@body input#oneoff_description', '') | |||||
->assertSeeIn('@button-cancel', 'Cancel') | |||||
->assertSeeIn('@button-action', 'Submit') | |||||
->click('@button-cancel'); | |||||
}) | |||||
->assertMissing('#oneoff-dialog') | |||||
->click('@user-finances #button-penalty') | |||||
->with(new Dialog('#oneoff-dialog'), function (Browser $browser) { | |||||
// Test input validation for a penalty | |||||
$browser->type('@body #oneoff_amount', '') | |||||
->type('@body #oneoff_description', '') | |||||
->click('@button-action') | |||||
->assertToast(Toast::TYPE_ERROR, 'Form validation error') | |||||
->assertVisible('@body #oneoff_amount.is-invalid') | |||||
->assertVisible('@body #oneoff_description.is-invalid') | |||||
->assertSeeIn( | |||||
'@body #oneoff_amount + span + .invalid-feedback', | |||||
'The amount field is required.' | |||||
) | |||||
->assertSeeIn( | |||||
'@body #oneoff_description + .invalid-feedback', | |||||
'The description field is required.' | |||||
); | |||||
// Test adding a penalty | |||||
$browser->type('@body #oneoff_amount', '12.35') | |||||
->type('@body #oneoff_description', 'Test penalty') | |||||
->click('@button-action') | |||||
->assertToast(Toast::TYPE_SUCCESS, 'The penalty has been added to the wallet successfully.'); | |||||
}) | |||||
->assertMissing('#oneoff-dialog') | |||||
->assertSeeIn('@user-finances .card-title span.text-danger', '-0,01 CHF'); | |||||
$this->assertSame(-1, $john->wallets()->first()->balance); | |||||
}); | |||||
} | |||||
} | } |