refactor: replace custom CRM with Monica fork
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
This commit is contained in:
235
tests/Browser/Auth/AuthControllerTest.php
Normal file
235
tests/Browser/Auth/AuthControllerTest.php
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Auth;
|
||||
|
||||
use Tests\TestCase;
|
||||
use GuzzleHttp\Client;
|
||||
use App\Models\User\User;
|
||||
use Tests\Traits\Asserts;
|
||||
use Tests\Traits\ApiSignIn;
|
||||
use Illuminate\Testing\TestResponse;
|
||||
use Laravel\Passport\ClientRepository;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
|
||||
|
||||
class AuthControllerTest extends TestCase
|
||||
{
|
||||
use ApiSignIn,
|
||||
Asserts;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if ($this->getActualConnection() != 'testing') {
|
||||
$this->markTestSkipped("Set DB_CONNECTION on 'testing' to run this test.");
|
||||
}
|
||||
}
|
||||
|
||||
protected $jsonStructureOAuthLogin = [
|
||||
'access_token',
|
||||
'expires_in',
|
||||
];
|
||||
|
||||
private const OAUTH_LOGIN_URL = 'http://localhost:8001/oauth/login';
|
||||
|
||||
public function test_oauth_login()
|
||||
{
|
||||
$repository = new ClientRepository();
|
||||
$client = null;
|
||||
try {
|
||||
$client = $repository->createPasswordGrantClient(
|
||||
null, config('app.name'), config('app.url')
|
||||
);
|
||||
|
||||
$this->setEnvironmentValue([
|
||||
'PASSPORT_PASSWORD_GRANT_CLIENT_ID' => $client->id,
|
||||
'PASSPORT_PASSWORD_GRANT_CLIENT_SECRET' => $client->secret,
|
||||
]);
|
||||
|
||||
$userPassword = 'password';
|
||||
$user = factory(User::class)->create([
|
||||
'password' => bcrypt($userPassword),
|
||||
]);
|
||||
|
||||
$response = $this->postClient(self::OAUTH_LOGIN_URL, [
|
||||
'email' => $user->email,
|
||||
'password' => $userPassword,
|
||||
]);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$response->assertJsonStructure($this->jsonStructureOAuthLogin);
|
||||
} finally {
|
||||
if ($client) {
|
||||
$repository->delete($client);
|
||||
}
|
||||
if ($user) {
|
||||
$user->account->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test_oauth_login_bad_password()
|
||||
{
|
||||
$repository = new ClientRepository();
|
||||
$client = null;
|
||||
try {
|
||||
$client = $repository->createPasswordGrantClient(
|
||||
null, config('app.name'), config('app.url')
|
||||
);
|
||||
|
||||
$this->setEnvironmentValue([
|
||||
'PASSPORT_PASSWORD_GRANT_CLIENT_ID' => $client->id,
|
||||
'PASSPORT_PASSWORD_GRANT_CLIENT_SECRET' => $client->secret,
|
||||
]);
|
||||
|
||||
$userPassword = 'password';
|
||||
$user = factory(User::class)->create([
|
||||
'password' => bcrypt($userPassword),
|
||||
]);
|
||||
|
||||
$response = $this->postClient(self::OAUTH_LOGIN_URL, [
|
||||
'email' => $user->email,
|
||||
'password' => 'wrongPassword',
|
||||
]);
|
||||
|
||||
$this->expectNotAuthorized($response);
|
||||
} finally {
|
||||
if ($client) {
|
||||
$repository->delete($client);
|
||||
}
|
||||
if ($user) {
|
||||
$user->account->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test_oauth_login_wrong_mail()
|
||||
{
|
||||
$response = $this->postClient(self::OAUTH_LOGIN_URL, [
|
||||
'email' => 'badmail',
|
||||
'password' => 'xx',
|
||||
]);
|
||||
|
||||
$response->assertStatus(422);
|
||||
$this->expectDataError($response, ['The email must be a valid email address.']);
|
||||
}
|
||||
|
||||
public function test_oauth_login_wrong_password()
|
||||
{
|
||||
$response = $this->postClient(self::OAUTH_LOGIN_URL, [
|
||||
'email' => 'mail@mail.com',
|
||||
'password' => 'xx',
|
||||
]);
|
||||
|
||||
$this->expectNotAuthorized($response);
|
||||
}
|
||||
|
||||
public function test_oauth_login_2fa()
|
||||
{
|
||||
$repository = new ClientRepository();
|
||||
$client = null;
|
||||
try {
|
||||
$client = $repository->createPasswordGrantClient(
|
||||
null, config('app.name'), config('app.url')
|
||||
);
|
||||
|
||||
$this->setEnvironmentValue([
|
||||
'PASSPORT_PASSWORD_GRANT_CLIENT_ID' => $client->id,
|
||||
'PASSPORT_PASSWORD_GRANT_CLIENT_SECRET' => $client->secret,
|
||||
]);
|
||||
|
||||
$userPassword = 'password';
|
||||
$user = factory(User::class)->create([
|
||||
'password' => bcrypt($userPassword),
|
||||
'google2fa_secret' => 'UFKZDTYO64WDEZPPQEO4HF3PC5UUTFLE',
|
||||
]);
|
||||
|
||||
$response = $this->postClient(self::OAUTH_LOGIN_URL, [
|
||||
'email' => $user->email,
|
||||
'password' => $userPassword,
|
||||
]);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$response->assertSee('Two Factor Authentication');
|
||||
} finally {
|
||||
if ($client) {
|
||||
$repository->delete($client);
|
||||
}
|
||||
if ($user) {
|
||||
$user->account->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getActualConnection()
|
||||
{
|
||||
$handle = fopen('.env', 'r');
|
||||
if (! $handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
$value = null;
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
if (preg_match('/DB_CONNECTION=(.{1,})/', $line, $matches)) {
|
||||
$value = $matches[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function setEnvironmentValue(array $values)
|
||||
{
|
||||
$envFile = app()->environmentFilePath();
|
||||
$str = file_get_contents($envFile);
|
||||
|
||||
if (count($values) > 0) {
|
||||
foreach ($values as $envKey => $envValue) {
|
||||
$str .= "\n"; // In case the searched variable is in the last line without \n
|
||||
$keyPosition = strpos($str, "{$envKey}=");
|
||||
$endOfLinePosition = strpos($str, "\n", $keyPosition);
|
||||
$oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);
|
||||
|
||||
// If key does not exist, add it
|
||||
if (! $keyPosition || ! $endOfLinePosition || ! $oldLine) {
|
||||
$str .= "{$envKey}={$envValue}\n";
|
||||
} else {
|
||||
$str = str_replace($oldLine, "{$envKey}={$envValue}", $str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$str = substr($str, 0, -1);
|
||||
|
||||
return file_put_contents($envFile, $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $param
|
||||
* @return TestResponse
|
||||
*/
|
||||
protected function postClient($path, $param)
|
||||
{
|
||||
try {
|
||||
$http = new Client([
|
||||
'timeout' => 30,
|
||||
]);
|
||||
$response = $http->post($path, [
|
||||
'form_params' => $param,
|
||||
]);
|
||||
} catch (\GuzzleHttp\Exception\RequestException $e) {
|
||||
$response = $e->getResponse();
|
||||
}
|
||||
|
||||
$factory = new HttpFoundationFactory();
|
||||
$response = $factory->createResponse($response);
|
||||
|
||||
return TestResponse::fromBaseResponse($response);
|
||||
}
|
||||
}
|
||||
21
tests/Browser/ExampleTest.php
Normal file
21
tests/Browser/ExampleTest.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser;
|
||||
|
||||
use Tests\DuskTestCase;
|
||||
|
||||
class ExampleTest extends DuskTestCase
|
||||
{
|
||||
/**
|
||||
* A basic browser test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicExample()
|
||||
{
|
||||
$this->browse(function ($browser) {
|
||||
$browser->visit('/')
|
||||
->assertSee('Login');
|
||||
});
|
||||
}
|
||||
}
|
||||
83
tests/Browser/Feature/UploadVCardTest.php
Normal file
83
tests/Browser/Feature/UploadVCardTest.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Feature;
|
||||
|
||||
use Tests\DuskTestCase;
|
||||
use Tests\Browser\Pages\ImportVCardUpload;
|
||||
|
||||
class UploadVCardTest extends DuskTestCase
|
||||
{
|
||||
/**
|
||||
* Make sure that the Add contact view has the link to the upload screen,
|
||||
* and that the screen contains the blank view.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_upload_vcard_is_accessible_from_add_contact_view()
|
||||
{
|
||||
$this->browse(function ($browser) {
|
||||
$browser->login()
|
||||
->visit('/people/add')
|
||||
->assertSee('import your contacts');
|
||||
|
||||
$browser->clickLink('import your contacts')
|
||||
->assertSee('You haven’t imported any contacts yet');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the Import button leads to the Import screen, and that
|
||||
* the cancel button leads to the Blank import screen.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_import_button_leads_to_import_screen()
|
||||
{
|
||||
$this->browse(function ($browser) {
|
||||
$browser->login()
|
||||
->visit('/settings/import')
|
||||
->clickLink('Import vCard')
|
||||
->assertPathIs('/settings/import/upload')
|
||||
->clickLink('Cancel')
|
||||
->assertPathIs('/settings/import');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a single contact from a valid vcard file.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_user_can_import_contacts_from_a_vcf_card()
|
||||
{
|
||||
$this->browse(function ($browser) {
|
||||
$browser->login()
|
||||
->visit('/settings/import')
|
||||
->clickLink('Import vCard')
|
||||
->attach('vcard', base_path('tests/stubs/single_vcard_stub.vcard'))
|
||||
->on(new ImportVCardUpload)
|
||||
->scrollTo('upload')
|
||||
->press('Upload')
|
||||
->assertSee('1 imported');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a contact from a broken vCard and see that it triggers an error.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_user_see_error_when_importing_broken_vcard()
|
||||
{
|
||||
$this->browse(function ($browser) {
|
||||
$browser->login()
|
||||
->visit('/settings/import')
|
||||
->clickLink('Import vCard')
|
||||
->attach('vcard', base_path('tests/stubs/broken_vcard_stub.vcard'))
|
||||
->on(new ImportVCardUpload)
|
||||
->scrollTo('upload')
|
||||
->press('Upload')
|
||||
->assertSee('The vcard must be a file of type: vcf, vcard.');
|
||||
});
|
||||
}
|
||||
}
|
||||
45
tests/Browser/Pages/DashboardValidate2fa.php
Normal file
45
tests/Browser/Pages/DashboardValidate2fa.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class DashboardValidate2fa extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/dashboard';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'verify' => "button[name='verify']",
|
||||
'otp' => '#one_time_password',
|
||||
];
|
||||
}
|
||||
}
|
||||
43
tests/Browser/Pages/HomePage.php
Normal file
43
tests/Browser/Pages/HomePage.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class HomePage extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@element' => '#selector',
|
||||
];
|
||||
}
|
||||
}
|
||||
44
tests/Browser/Pages/ImportVCardUpload.php
Normal file
44
tests/Browser/Pages/ImportVCardUpload.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class ImportVCardUpload extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/settings/import/upload';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'upload' => '#upload',
|
||||
];
|
||||
}
|
||||
}
|
||||
21
tests/Browser/Pages/Page.php
Normal file
21
tests/Browser/Pages/Page.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Page as BasePage;
|
||||
|
||||
abstract class Page extends BasePage
|
||||
{
|
||||
/**
|
||||
* Get the global element shortcuts for the site.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function siteElements()
|
||||
{
|
||||
return [
|
||||
'@link' => "a[@href='link']",
|
||||
'alert' => '.alert',
|
||||
];
|
||||
}
|
||||
}
|
||||
45
tests/Browser/Pages/Settings/SettingsPersonnalization.php
Normal file
45
tests/Browser/Pages/Settings/SettingsPersonnalization.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages\Settings;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Tests\Browser\Pages\Page;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class SettingsPersonnalization extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/settings/personalization';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@reminder-rule-label' => '.reminder-rule-7 > span',
|
||||
];
|
||||
}
|
||||
}
|
||||
44
tests/Browser/Pages/SettingsDAV.php
Normal file
44
tests/Browser/Pages/SettingsDAV.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class SettingsDAV extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/settings/dav';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'dav_url_base' => '#dav_url_base',
|
||||
];
|
||||
}
|
||||
}
|
||||
54
tests/Browser/Pages/SettingsSecurity.php
Normal file
54
tests/Browser/Pages/SettingsSecurity.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class SettingsSecurity extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/settings/security';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'two_factor_link' => "a:contains('Enable Two Factor Authentication')",
|
||||
'barcode' => '#barcode',
|
||||
'secretkey' => '#secretkey',
|
||||
'buttonVerify' => "button[name='verify']",
|
||||
'enableVerify' => '#verify1',
|
||||
'disableVerify' => '#verify2',
|
||||
'otpenable' => '#one_time_password1',
|
||||
'otpdisable' => '#one_time_password2',
|
||||
'enableModal' => '#enableModal',
|
||||
'disableModal' => '#disableModal',
|
||||
'registerModal' => '#registerModal',
|
||||
];
|
||||
}
|
||||
}
|
||||
45
tests/Browser/Pages/SettingsSecurity2faDisable.php
Normal file
45
tests/Browser/Pages/SettingsSecurity2faDisable.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class SettingsSecurity2faDisable extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/settings/security/2fa-disable';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'verify' => "button[name='verify']",
|
||||
'otp' => '#one_time_password',
|
||||
];
|
||||
}
|
||||
}
|
||||
47
tests/Browser/Pages/SettingsSecurity2faEnable.php
Normal file
47
tests/Browser/Pages/SettingsSecurity2faEnable.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class SettingsSecurity2faEnable extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/settings/security/2fa-enable';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'barcode' => '#barcode',
|
||||
'secretkey' => '#secretkey',
|
||||
'verify' => "button[name='verify']",
|
||||
'otp' => '#one_time_password',
|
||||
];
|
||||
}
|
||||
}
|
||||
44
tests/Browser/Pages/Validate2fa.php
Normal file
44
tests/Browser/Pages/Validate2fa.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Pages;
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class Validate2fa extends Page
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* Get the URL for the page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return '/validate2fa';
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the browser is on the page.
|
||||
*
|
||||
* @param Browser $browser
|
||||
* @return void
|
||||
*/
|
||||
public function assert(Browser $browser)
|
||||
{
|
||||
$browser->assertPathIs($this->url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element shortcuts for the page.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function elements()
|
||||
{
|
||||
return [
|
||||
'@element' => '#selector',
|
||||
];
|
||||
}
|
||||
}
|
||||
23
tests/Browser/Settings/DAVControllerTest.php
Normal file
23
tests/Browser/Settings/DAVControllerTest.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Settings;
|
||||
|
||||
use Tests\DuskTestCase;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Tests\Browser\Pages\SettingsDAV;
|
||||
|
||||
class DAVControllerTest extends DuskTestCase
|
||||
{
|
||||
/**
|
||||
* Test if the dav url is present.
|
||||
*/
|
||||
public function test_it_has_dav_url()
|
||||
{
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser->login()
|
||||
->visit(new SettingsDAV)
|
||||
->assertVisible('dav_url_base')
|
||||
->assertSourceHas(config('app.url').'/dav');
|
||||
});
|
||||
}
|
||||
}
|
||||
342
tests/Browser/Settings/MultiFAControllerTest.php
Normal file
342
tests/Browser/Settings/MultiFAControllerTest.php
Normal file
@@ -0,0 +1,342 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser\Settings;
|
||||
|
||||
use Zxing\QrReader;
|
||||
use Tests\DuskTestCase;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Illuminate\Console\Application;
|
||||
use Tests\Browser\Pages\SettingsSecurity;
|
||||
use Tests\Browser\Pages\DashboardValidate2fa;
|
||||
|
||||
class MultiFAControllerTest extends DuskTestCase
|
||||
{
|
||||
/**
|
||||
* Cleanup.
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
exec(Application::formatCommandString('2fa:deactivate --force --email=admin@admin.com'), $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the user has 2fa Enable Link in Security Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testHasSettings2faEnableLink()
|
||||
{
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->assertSeeLink('Enable Two Factor Authentication');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the user has WebAuthn Enable Link in Security Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testHasSettingsWebAuthnEnableLink()
|
||||
{
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->assertSeeLink('Add a new security key');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the barcode generated in 2fa Enable Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testHas2faEnableBarCode()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal')
|
||||
->assertVisible('barcode')
|
||||
->assertVisible('secretkey');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the barcode generated in 2fa Enable Page.
|
||||
*
|
||||
* @group multifa
|
||||
* @group multifabarcode
|
||||
*/
|
||||
public function testBarCodeContent()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser =
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal');
|
||||
|
||||
// \Facebook\WebDriver\Remote\RemoteWebElement
|
||||
$barcode = $browser->element('barcode');
|
||||
$imgsrc = $barcode->getAttribute('src');
|
||||
|
||||
$key = $this->unparseBarcode($imgsrc);
|
||||
$this->assertEquals(32, strlen($key));
|
||||
|
||||
$this->assertEquals($browser->text('secretkey'), $key);
|
||||
});
|
||||
}
|
||||
|
||||
private function unparseBarcode($imgsrc)
|
||||
{
|
||||
$this->assertStringStartsWith('data:image/png', $imgsrc);
|
||||
|
||||
$imgcode = str_replace('data:image/png;base64,', '', $imgsrc);
|
||||
|
||||
$qrcode = new QrReader(base64_decode($imgcode), QrReader::SOURCE_TYPE_BLOB);
|
||||
$text = $qrcode->text();
|
||||
$this->assertStringStartsWith('otpauth://totp/', $text);
|
||||
|
||||
// unparse $text
|
||||
// See PragmaRX\Google2FA\Support\QRCode getQRCodeUrl
|
||||
// example :
|
||||
//otpauth://totp/monicalocal.test:admin%40admin.com?secret=H25L7JLI7I57KYE7U53BIIOUELWXMRE6&issuer=monicalocal.test
|
||||
|
||||
$ret = preg_match('@^otpauth://totp/([^:]+):([^?]+)\?secret=([^&]+)&issuer=(.+)@i', $text, $matches);
|
||||
$this->assertEquals(1, $ret, 'otp content does not match format');
|
||||
$this->assertCount(5, $matches);
|
||||
|
||||
return $matches[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the 2fa Enable Page with wrong code.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testEnable2faWrongCode()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser =
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal')
|
||||
->type('otpenable', '000000')
|
||||
->scrollTo('enableVerify')
|
||||
->press('enableVerify')
|
||||
->waitUntilMissing('enableModal');
|
||||
|
||||
$this->assertTrue($this->hasNotification($browser));
|
||||
$notification = $this->getNotification($browser);
|
||||
$this->assertStringContainsString('error', $notification->getAttribute('class'));
|
||||
$this->assertStringContainsString('Two Factor Authentication', $notification->getText());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the 2fa Enable Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testEnable2fa()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser =
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal');
|
||||
|
||||
$this->enable2fa($browser);
|
||||
});
|
||||
}
|
||||
|
||||
private function enable2fa(Browser $browser)
|
||||
{
|
||||
$secretkey = $browser->waitFor('enableModal')
|
||||
->text('secretkey');
|
||||
|
||||
$google2fa = new \PragmaRX\Google2FA\Google2FA();
|
||||
$one_time_password = $google2fa->getCurrentOtp($secretkey);
|
||||
$browser->type('otpenable', $one_time_password);
|
||||
|
||||
$browser = $browser->scrollTo('enableVerify')
|
||||
->press('enableVerify')
|
||||
->waitUntilMissing('enableModal');
|
||||
|
||||
$this->assertTrue($this->hasNotification($browser));
|
||||
$notification = $this->getNotification($browser);
|
||||
$this->assertStringContainsString('success', $notification->getAttribute('class'));
|
||||
$this->assertStringContainsString('Two Factor Authentication', $notification->getText());
|
||||
|
||||
// TODO: test if user has 2fa enabled actually
|
||||
// TODO: test if session token auth is right
|
||||
|
||||
$browser->assertSeeLink('Disable Two Factor Authentication');
|
||||
|
||||
return $secretkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the 2fa Enable Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testEnable2faLoginWrongCode()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$user = call_user_func(Browser::$userResolver);
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser =
|
||||
$browser->loginAs($user)
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal');
|
||||
|
||||
$secretkey = $this->enable2fa($browser);
|
||||
|
||||
$browser =
|
||||
$browser->clickLink('Logout')
|
||||
->loginAs($user)
|
||||
->visit(new DashboardValidate2fa)
|
||||
->assertVisible('otp')
|
||||
->type('otp', '000000')
|
||||
->press('verify');
|
||||
|
||||
$this->assertTrue($this->hasDivAlert($browser));
|
||||
$notification = $this->getDivAlert($browser);
|
||||
$this->assertStringContainsString('alert-danger', $notification->getAttribute('class'));
|
||||
$this->assertStringContainsString('The two factor authentication has failed.', $notification->getText());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the 2fa Enable Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testEnable2faLogin()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$user = call_user_func(Browser::$userResolver);
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser =
|
||||
$browser->loginAs($user)
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal');
|
||||
|
||||
$secretkey = $this->enable2fa($browser);
|
||||
$google2fa = new \PragmaRX\Google2FA\Google2FA();
|
||||
$one_time_password = $google2fa->getCurrentOtp($secretkey);
|
||||
|
||||
$browser =
|
||||
$browser->clickLink('Logout')
|
||||
->loginAs($user)
|
||||
->visit(new DashboardValidate2fa)
|
||||
->assertVisible('otp')
|
||||
->type('otp', $one_time_password)
|
||||
->press('verify');
|
||||
|
||||
$this->assertFalse($this->hasDivAlert($browser));
|
||||
$browser->assertPathIs('/dashboard');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test 2fa Enable Page and Disable Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testEnable2faDisable2fa()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser =
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal');
|
||||
|
||||
$secretkey = $this->enable2fa($browser);
|
||||
$google2fa = new \PragmaRX\Google2FA\Google2FA();
|
||||
$one_time_password = $google2fa->getCurrentOtp($secretkey);
|
||||
|
||||
$browser =
|
||||
$browser->clickLink('Disable Two Factor Authentication')
|
||||
->waitFor('disableModal')
|
||||
->assertVisible('otpdisable')
|
||||
->type('otpdisable', $one_time_password)
|
||||
->scrollTo('disableVerify')
|
||||
->press('disableVerify')
|
||||
->waitUntilMissing('enableModal');
|
||||
|
||||
$this->assertTrue($this->hasNotification($browser));
|
||||
$notification = $this->getNotification($browser);
|
||||
$this->assertStringContainsString('success', $notification->getAttribute('class'));
|
||||
$this->assertStringContainsString('Two Factor Authentication', $notification->getText());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test 2fa Enable Page and Disable Page.
|
||||
*
|
||||
* @group multifa
|
||||
*/
|
||||
public function testEnable2faDisable2faWrongCode()
|
||||
{
|
||||
$this->markTestIncomplete('Ignore 2fa tests for now.');
|
||||
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser =
|
||||
$browser->login()
|
||||
->visit(new SettingsSecurity)
|
||||
->scrollTo('two_factor_link')
|
||||
->clickLink('Enable Two Factor Authentication')
|
||||
->waitFor('enableModal');
|
||||
|
||||
$this->enable2fa($browser);
|
||||
|
||||
$browser =
|
||||
$browser->clickLink('Disable Two Factor Authentication')
|
||||
->waitFor('disableModal')
|
||||
->assertVisible('otpdisable')
|
||||
->type('otpdisable', '000000')
|
||||
->scrollTo('disableVerify')
|
||||
->press('disableVerify')
|
||||
->waitUntilMissing('disableModal');
|
||||
|
||||
$this->assertTrue($this->hasNotification($browser));
|
||||
|
||||
$res = $browser->elements('.notification');
|
||||
$notification = $res[1];
|
||||
|
||||
$this->assertStringContainsString('error', $notification->getAttribute('class'));
|
||||
$this->assertStringContainsString('Two Factor Authentication', $notification->getText());
|
||||
});
|
||||
}
|
||||
}
|
||||
2
tests/Browser/console/.gitignore
vendored
Normal file
2
tests/Browser/console/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
2
tests/Browser/screenshots/.gitignore
vendored
Normal file
2
tests/Browser/screenshots/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
Reference in New Issue
Block a user