Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F8224679
UserFinancesTest.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
UserFinancesTest.php
View Options
<?php
namespace
Tests\Browser\Reseller
;
use
App\Discount
;
use
App\Transaction
;
use
App\User
;
use
App\Wallet
;
use
Carbon\Carbon
;
use
Tests\Browser
;
use
Tests\Browser\Components\Dialog
;
use
Tests\Browser\Components\Toast
;
use
Tests\Browser\Pages\Admin\User
as
UserPage
;
use
Tests\Browser\Pages\Dashboard
;
use
Tests\Browser\Pages\Home
;
use
Tests\TestCaseDusk
;
class
UserFinancesTest
extends
TestCaseDusk
{
/**
* {@inheritDoc}
*/
public
function
setUp
():
void
{
parent
::
setUp
();
self
::
useResellerUrl
();
$john
=
$this
->
getTestUser
(
'john@kolab.org'
);
$wallet
=
$john
->
wallets
()->
first
();
$wallet
->
discount
()->
dissociate
();
$wallet
->
balance
=
0
;
$wallet
->
save
();
$wallet
->
setSettings
([
'mollie_id'
=>
null
,
'stripe_id'
=>
null
]);
}
/**
* Test Finances tab (and transactions)
*/
public
function
testFinances
():
void
{
// Assert Jack's Finances tab
$this
->
browse
(
function
(
Browser
$browser
)
{
$jack
=
$this
->
getTestUser
(
'jack@kolab.org'
);
$wallet
=
$jack
->
wallets
()->
first
();
$wallet
->
transactions
()->
delete
();
$wallet
->
setSetting
(
'stripe_id'
,
'abc'
);
$page
=
new
UserPage
(
$jack
->
id
);
$browser
->
visit
(
new
Home
())
->
submitLogon
(
'reseller@'
.
\config
(
'app.domain'
),
\App\Utils
::
generatePassphrase
(),
true
)
->
on
(
new
Dashboard
())
->
visit
(
$page
)
->
on
(
$page
)
->
assertSeeIn
(
'@nav #tab-finances'
,
'Finances'
)
->
with
(
'@user-finances'
,
function
(
Browser
$browser
)
{
$browser
->
waitUntilMissing
(
'.app-loader'
)
->
assertSeeIn
(
'.card-title:first-child'
,
'Account balance'
)
->
assertSeeIn
(
'.card-title:first-child .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'
)
->
assertSeeIn
(
'.row:nth-child(2) label'
,
'Stripe ID'
)
->
assertSeeIn
(
'.row:nth-child(2) a'
,
'abc'
);
})
->
assertSeeIn
(
'h2:nth-of-type(2)'
,
'Transactions'
)
->
with
(
'table'
,
function
(
Browser
$browser
)
{
$browser
->
assertMissing
(
'tbody'
)
->
assertSeeIn
(
'tfoot td'
,
"There are no transactions for this account."
);
})
->
assertMissing
(
'table + button'
);
});
});
// Assert John's Finances tab (with discount, and debit)
$this
->
browse
(
function
(
Browser
$browser
)
{
$john
=
$this
->
getTestUser
(
'john@kolab.org'
);
$page
=
new
UserPage
(
$john
->
id
);
$discount
=
Discount
::
where
(
'code'
,
'TEST'
)->
first
();
$wallet
=
$john
->
wallet
();
$wallet
->
transactions
()->
delete
();
$wallet
->
discount
()->
associate
(
$discount
);
$wallet
->
debit
(
2010
);
$wallet
->
save
();
// Create test transactions
$transaction
=
Transaction
::
create
([
'user_email'
=>
'jeroen@jeroen.jeroen'
,
'object_id'
=>
$wallet
->
id
,
'object_type'
=>
Wallet
::
class
,
'type'
=>
Transaction
::
WALLET_CREDIT
,
'amount'
=>
100
,
'description'
=>
'Payment'
,
]);
$transaction
->
created_at
=
Carbon
::
now
()->
subMonth
();
$transaction
->
save
();
// Click the managed-by link on Jack's page
$browser
->
click
(
'@user-info #manager a'
)
->
on
(
$page
)
->
with
(
'@user-finances'
,
function
(
Browser
$browser
)
{
$browser
->
waitUntilMissing
(
'.app-loader'
)
->
assertSeeIn
(
'.card-title:first-child'
,
'Account balance'
)
->
assertSeeIn
(
'.card-title:first-child .text-danger'
,
'-20,10 CHF'
)
->
with
(
'form'
,
function
(
Browser
$browser
)
{
$browser
->
assertElementsCount
(
'.row'
,
1
)
->
assertSeeIn
(
'.row:nth-child(1) label'
,
'Discount'
)
->
assertSeeIn
(
'.row:nth-child(1) #discount span'
,
'10% - Test voucher'
);
})
->
assertSeeIn
(
'h2:nth-of-type(2)'
,
'Transactions'
)
->
with
(
'table'
,
function
(
Browser
$browser
)
{
$browser
->
assertElementsCount
(
'tbody tr'
,
2
)
->
assertMissing
(
'tfoot'
);
if
(!
$browser
->
isPhone
())
{
$browser
->
assertSeeIn
(
'tbody tr:last-child td.email'
,
'jeroen@jeroen.jeroen'
);
}
});
});
});
// Now we go to Ned's info page, he's a controller on John's wallet
$this
->
browse
(
function
(
Browser
$browser
)
{
$ned
=
$this
->
getTestUser
(
'ned@kolab.org'
);
$wallet
=
$ned
->
wallets
()->
first
();
$wallet
->
balance
=
0
;
$wallet
->
save
();
$page
=
new
UserPage
(
$ned
->
id
);
$browser
->
click
(
'@nav #tab-users'
)
->
click
(
'@user-users tbody tr:nth-child(4) td:first-child a'
)
->
on
(
$page
)
->
with
(
'@user-finances'
,
function
(
Browser
$browser
)
{
$browser
->
waitUntilMissing
(
'.app-loader'
)
->
assertSeeIn
(
'.card-title:first-child'
,
'Account balance'
)
->
assertSeeIn
(
'.card-title:first-child .text-success'
,
'0,00 CHF'
)
->
with
(
'form'
,
function
(
Browser
$browser
)
{
$browser
->
assertElementsCount
(
'.row'
,
1
)
->
assertSeeIn
(
'.row:nth-child(1) label'
,
'Discount'
)
->
assertSeeIn
(
'.row:nth-child(1) #discount span'
,
'none'
);
})
->
assertSeeIn
(
'h2:nth-of-type(2)'
,
'Transactions'
)
->
with
(
'table'
,
function
(
Browser
$browser
)
{
$browser
->
assertMissing
(
'tbody'
)
->
assertSeeIn
(
'tfoot td'
,
"There are no transactions for this account."
);
})
->
assertMissing
(
'table + button'
);
});
});
}
/**
* Test editing wallet discount
*
* @depends testFinances
*/
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'
,
'4,50 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,41 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'
,
'5,00 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,90 CHF/month'
)
->
assertMissing
(
'table + .hint'
);
});
});
}
/**
* Test awarding/penalizing a wallet
*
* @depends testFinances
*/
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'
)
->
waitUntilMissing
(
'.app-loader'
)
->
with
(
'table'
,
function
(
Browser
$browser
)
{
$browser
->
assertElementsCount
(
'tbody tr'
,
3
)
->
assertMissing
(
'tfoot'
)
->
assertSeeIn
(
'tbody tr:first-child td.description'
,
'Bonus: Test bonus'
)
->
assertSeeIn
(
'tbody tr:first-child td.price'
,
'12,34 CHF'
);
if
(!
$browser
->
isPhone
())
{
$browser
->
assertSeeIn
(
'tbody tr:first-child td.email'
,
'reseller@'
.
\config
(
'app.domain'
));
}
});
$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
);
});
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, Jul 10, 12:12 AM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1057289
Default Alt Text
UserFinancesTest.php (15 KB)
Attached To
Mode
R2 kolab
Attached
Detach File
Event Timeline
Log In to Comment