Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120824213
UserFinancesTest.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
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\Utils
;
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
{
protected
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'
),
Utils
::
generatePassphrase
(),
true
)
->
on
(
new
Dashboard
())
->
visit
(
$page
)
->
on
(
$page
)
->
assertSeeIn
(
'@nav #tab-finances'
,
'Finances'
)
->
with
(
'@user-finances'
,
static
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'
,
static
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'
,
static
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'
,
static
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'
,
static
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'
,
static
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'
,
static
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'
,
static
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'
,
static
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'
),
static
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'
),
static
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'
,
static
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'
),
static
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'
,
static
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'
),
static
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'
),
static
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'
,
static
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'
),
static
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'
),
static
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, Apr 24, 10:18 AM (2 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18866827
Default Alt Text
UserFinancesTest.php (15 KB)
Attached To
Mode
rK kolab
Attached
Detach File
Event Timeline