OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
59
tests/Support/AcceptanceTester.php
Normal file
59
tests/Support/AcceptanceTester.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Support;
|
||||
|
||||
use Facebook\WebDriver\Exception\ElementClickInterceptedException;
|
||||
use Facebook\WebDriver\Exception\StaleElementReferenceException;
|
||||
|
||||
/**
|
||||
* Inherited Methods
|
||||
*
|
||||
* @method void wantTo($text)
|
||||
* @method void wantToTest($text)
|
||||
* @method void execute($callable)
|
||||
*/
|
||||
class AcceptanceTester extends \Codeception\Actor
|
||||
{
|
||||
use _generated\AcceptanceTesterActions;
|
||||
|
||||
/*
|
||||
* Click on an element with retries and waits
|
||||
*/
|
||||
public function clickWithRetry($selector, $timeout = 10)
|
||||
{
|
||||
$maxAttempts = 3;
|
||||
$attempt = 1;
|
||||
|
||||
while ($attempt <= $maxAttempts) {
|
||||
try {
|
||||
// Wait for element to be clickable
|
||||
$this->waitForElementClickable($selector, $timeout);
|
||||
|
||||
// Scroll element into view
|
||||
$this->executeJS("document.querySelector('".$selector."').scrollIntoView({behavior: 'smooth', block: 'center'});");
|
||||
$this->wait(1); // Small wait after scroll
|
||||
|
||||
// Try to click
|
||||
$this->click($selector);
|
||||
|
||||
return;
|
||||
} catch (ElementClickInterceptedException|StaleElementReferenceException $e) {
|
||||
if ($attempt === $maxAttempts) {
|
||||
throw $e;
|
||||
}
|
||||
$this->wait(1);
|
||||
$attempt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take debug screenshot on failure
|
||||
*/
|
||||
public function _failed(\Codeception\TestInterface $test, $fail)
|
||||
{
|
||||
$this->makeScreenshot('failed_'.$test->getName());
|
||||
}
|
||||
}
|
||||
22
tests/Support/ApiTester.php
Normal file
22
tests/Support/ApiTester.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Support;
|
||||
|
||||
/**
|
||||
* Inherited Methods
|
||||
*
|
||||
* @method void wantToTest($text)
|
||||
* @method void wantTo($text)
|
||||
* @method void execute($callable)
|
||||
* @method void expectTo($prediction)
|
||||
* @method void expect($prediction)
|
||||
* @method void amGoingTo($argumentation)
|
||||
* @method void am($role)
|
||||
* @method void lookForwardTo($achieveValue)
|
||||
* @method void comment($description)
|
||||
* @method void pause()
|
||||
*/
|
||||
class ApiTester extends \Codeception\Actor
|
||||
{
|
||||
use _generated\ApiTesterActions;
|
||||
}
|
||||
0
tests/Support/Data/.gitkeep
Normal file
0
tests/Support/Data/.gitkeep
Normal file
36
tests/Support/Helper/Acceptance.php
Normal file
36
tests/Support/Helper/Acceptance.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Support\Helper;
|
||||
|
||||
use Codeception\Module;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Leantime\Core\Application;
|
||||
|
||||
class Acceptance extends Module
|
||||
{
|
||||
protected Application $app;
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
$this->app = require dirname(__DIR__, 2).'/bootstrap.php';
|
||||
|
||||
if (! defined('BASE_URL')) {
|
||||
define('BASE_URL', 'https://leantime-dev');
|
||||
}
|
||||
}
|
||||
|
||||
public function getApplication(): Application
|
||||
{
|
||||
return $this->app;
|
||||
}
|
||||
|
||||
public function setCSRFToken()
|
||||
{
|
||||
$token = bin2hex(random_bytes(32));
|
||||
Session::put('_token', $token);
|
||||
Session::save();
|
||||
|
||||
// Set the token in the cookie as well
|
||||
$this->getModule('WebDriver')->setCookie('XSRF-TOKEN', $token);
|
||||
}
|
||||
}
|
||||
27
tests/Support/Helper/Api.php
Normal file
27
tests/Support/Helper/Api.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Support\Helper;
|
||||
|
||||
use Codeception\Module;
|
||||
use Leantime\Core\Application;
|
||||
|
||||
class Api extends Module
|
||||
{
|
||||
protected Application $app;
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
$this->app = require dirname(__DIR__, 2).'/bootstrap.php';
|
||||
|
||||
}
|
||||
|
||||
public function getApplication(): Application
|
||||
{
|
||||
return $this->app;
|
||||
}
|
||||
|
||||
public function haveHttpHeader($header, $value)
|
||||
{
|
||||
$this->getModule('REST')->haveHttpHeader($header, $value);
|
||||
}
|
||||
}
|
||||
39
tests/Support/Helper/Unit.php
Normal file
39
tests/Support/Helper/Unit.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Support\Helper;
|
||||
|
||||
use Codeception\Module;
|
||||
use Leantime\Core\Application;
|
||||
|
||||
class Unit extends Module
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
$this->app = bootstrap_minimal_app();
|
||||
}
|
||||
|
||||
public function getApplication()
|
||||
{
|
||||
return $this->app;
|
||||
}
|
||||
|
||||
public function haveInDatabase($table, array $data)
|
||||
{
|
||||
return $this->getModule('Db')->haveInDatabase($table, $data);
|
||||
}
|
||||
|
||||
public function seeInDatabase($table, array $criteria)
|
||||
{
|
||||
return $this->getModule('Db')->seeInDatabase($table, $criteria);
|
||||
}
|
||||
|
||||
public function dontSeeInDatabase($table, array $criteria)
|
||||
{
|
||||
return $this->getModule('Db')->dontSeeInDatabase($table, $criteria);
|
||||
}
|
||||
}
|
||||
81
tests/Support/Page/Acceptance/Install.php
Normal file
81
tests/Support/Page/Acceptance/Install.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Support\Page\Acceptance;
|
||||
|
||||
use Codeception\Util\Fixtures;
|
||||
use Tests\Support\AcceptanceTester;
|
||||
|
||||
class Install
|
||||
{
|
||||
protected AcceptanceTester $I;
|
||||
|
||||
protected $app;
|
||||
|
||||
public function __construct(AcceptanceTester $I)
|
||||
{
|
||||
$this->I = $I;
|
||||
$this->app = $I->getApplication();
|
||||
}
|
||||
|
||||
public function install($email, $password, $firstname, $lastname, $company): void
|
||||
{
|
||||
if (Fixtures::exists('installed')) {
|
||||
$this->suppressModals();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->I->amOnPage('/install');
|
||||
$this->I->fillField(['name' => 'email'], $email);
|
||||
$this->I->fillField(['name' => 'firstname'], $firstname);
|
||||
$this->I->fillField(['name' => 'lastname'], $lastname);
|
||||
$this->I->fillField(['name' => 'company'], $company);
|
||||
$this->I->click('Install');
|
||||
|
||||
// A successful install redirects straight into the onboarding wizard
|
||||
// (auth/userInvite), starting on the "Setting Account Details" step —
|
||||
// there is no longer a standalone success .alert page. Wait for the
|
||||
// jobTitle field (the first field this method fills) to confirm the
|
||||
// step has rendered before continuing.
|
||||
$this->I->waitForElementVisible(['name' => 'jobTitle'], 90);
|
||||
|
||||
$this->I->fillField(['name' => 'jobTitle'], 'CEO');
|
||||
|
||||
$this->I->fillField(['name' => 'password'], $password);
|
||||
|
||||
$this->I->click('Next');
|
||||
$this->I->waitForText('Determining A Visual Experience', 90);
|
||||
|
||||
$this->I->click('Next');
|
||||
$this->I->waitForText('Creating A Comfortable View', 90);
|
||||
|
||||
$this->I->click('Next');
|
||||
$this->I->waitForText('Shaping A Daily Flow', 90);
|
||||
|
||||
$this->I->click('Next');
|
||||
$this->I->waitForText('Your Leantime journey is about to begin', 90);
|
||||
|
||||
$this->I->click('Complete Sign up');
|
||||
|
||||
Fixtures::add('installed', true);
|
||||
$this->suppressModals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppress all helper modals for testing
|
||||
*/
|
||||
private function suppressModals(): void
|
||||
{
|
||||
$userService = $this->app->make(\Leantime\Domain\Users\Services\Users::class);
|
||||
session(['userdata.id' => 1]);
|
||||
|
||||
// Suppress all known modals
|
||||
$userService->updateUserSettings('modals', 'projectDashboard', true);
|
||||
$userService->updateUserSettings('modals', 'home', true);
|
||||
$userService->updateUserSettings('modals', 'kanban', true);
|
||||
$userService->updateUserSettings('modals', 'roadmap', true);
|
||||
$userService->updateUserSettings('modals', 'goals', true);
|
||||
}
|
||||
}
|
||||
63
tests/Support/Page/Acceptance/Login.php
Normal file
63
tests/Support/Page/Acceptance/Login.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Support\Page\Acceptance;
|
||||
|
||||
use Codeception\Util\Fixtures;
|
||||
|
||||
class Login
|
||||
{
|
||||
/**
|
||||
* @var \Tests\Support\AcceptanceTester;
|
||||
*/
|
||||
protected $I;
|
||||
|
||||
public function __construct(\Tests\Support\AcceptanceTester $I, Install $installPage)
|
||||
{
|
||||
$this->I = $I;
|
||||
$this->installPage = $installPage;
|
||||
}
|
||||
|
||||
public function login($username, $password)
|
||||
{
|
||||
if ($this->loadSessionShapshot('leantime_session')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! Fixtures::exists('installed')) {
|
||||
$this->installPage->install(
|
||||
'test@leantime.io',
|
||||
'Test123456!',
|
||||
'John',
|
||||
'Smith',
|
||||
'Smith & Co'
|
||||
);
|
||||
}
|
||||
|
||||
$this->I->amOnPage('/auth/login');
|
||||
$this->I->fillField(['name' => 'username'], $username);
|
||||
$this->I->fillField(['name' => 'password'], $password);
|
||||
$this->I->click('Login');
|
||||
$this->I->waitForElementVisible('.welcome-widget', 120);
|
||||
$this->I->see('Hi John');
|
||||
|
||||
$this->saveSessionSnapshot('leantime_session');
|
||||
}
|
||||
|
||||
protected function loadSessionShapshot(string $name): bool
|
||||
{
|
||||
if (! Fixtures::exists($name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->I->setCookie($name, Fixtures::get($name));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function saveSessionSnapshot(string $name): void
|
||||
{
|
||||
Fixtures::add($name, $this->I->grabCookie($name));
|
||||
}
|
||||
}
|
||||
30
tests/Support/UnitTester.php
Normal file
30
tests/Support/UnitTester.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Support;
|
||||
|
||||
/**
|
||||
* Inherited Methods
|
||||
*
|
||||
* @method void wantTo($text)
|
||||
* @method void wantToTest($text)
|
||||
* @method void execute($callable)
|
||||
* @method void expectTo($prediction)
|
||||
* @method void expect($prediction)
|
||||
* @method void amGoingTo($argumentation)
|
||||
* @method void am($role)
|
||||
* @method void lookForwardTo($achieveValue)
|
||||
* @method void comment($description)
|
||||
* @method void pause($vars = [])
|
||||
*
|
||||
* @SuppressWarnings(PHPMD)
|
||||
*/
|
||||
class UnitTester extends \Codeception\Actor
|
||||
{
|
||||
use _generated\UnitTesterActions;
|
||||
|
||||
/**
|
||||
* Define custom actions here
|
||||
*/
|
||||
}
|
||||
2
tests/Support/_generated/.gitignore
vendored
Normal file
2
tests/Support/_generated/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
Reference in New Issue
Block a user