From 9d821df92341352768bb42fb0e085b4c4a778f64 Mon Sep 17 00:00:00 2001 From: Yuriy Bakhtin Date: Fri, 8 Sep 2023 13:28:47 +0200 Subject: [PATCH] Test to create Answers and voting system --- tests/codeception.yml | 46 +++---- tests/codeception/_bootstrap.php | 70 +++++------ tests/codeception/_output/.gitignore | 6 +- .../codeception/_support/AcceptanceTester.php | 86 ++++++++++++- .../_support/_generated/.gitignore | 6 +- tests/codeception/acceptance.suite.yml | 48 ++++---- tests/codeception/acceptance/QuestionCest.php | 114 +++++++++++------- tests/codeception/acceptance/_bootstrap.php | 12 +- tests/codeception/config/functional.php | 3 - tests/codeception/config/unit.php | 4 +- .../fixtures/QuestionAnswerFixture.php | 34 +++--- .../fixtures/QuestionAnswerVoteFixture.php | 37 +++--- .../codeception/fixtures/QuestionFixture.php | 41 ++++--- tests/codeception/fixtures/data/question.php | 14 +-- .../fixtures/data/question_answer.php | 14 +-- .../fixtures/data/question_answer_vote.php | 14 +-- tests/codeception/unit.suite.yml | 28 ++--- tests/codeception/unit/_bootstrap.php | 12 +- tests/config/common.php | 10 +- tests/config/functional.php | 5 - tests/config/test.php | 32 ++--- tests/config/unit.php | 10 +- 22 files changed, 370 insertions(+), 276 deletions(-) delete mode 100644 tests/codeception/config/functional.php delete mode 100644 tests/config/functional.php diff --git a/tests/codeception.yml b/tests/codeception.yml index e2b39de..cc1c890 100644 --- a/tests/codeception.yml +++ b/tests/codeception.yml @@ -1,23 +1,23 @@ -actor: Tester -namespace: questions -bootstrap: _bootstrap.php -settings: - suite_class: \PHPUnit_Framework_TestSuite - colors: true - shuffle: false - memory_limit: 1024M - log: true - - # This value controls whether PHPUnit attempts to backup global variables - # See https://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.backupGlobals - backup_globals: true -paths: - tests: codeception - log: codeception/_output - data: codeception/_data - helpers: codeception/_support - envs: ../../../humhub/tests/config/env -config: - # the entry script URL (with host info) for functional and acceptance tests - # PLEASE ADJUST IT TO THE ACTUAL ENTRY SCRIPT URL - test_entry_url: http://localhost:8080/index-test.php +actor: Tester +namespace: questions +bootstrap: _bootstrap.php +settings: + suite_class: \PHPUnit_Framework_TestSuite + colors: true + shuffle: false + memory_limit: 1024M + log: true + + # This value controls whether PHPUnit attempts to backup global variables + # See https://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.backupGlobals + backup_globals: true +paths: + tests: codeception + log: codeception/_output + data: codeception/_data + helpers: codeception/_support + envs: ../../../humhub/tests/config/env +config: + # the entry script URL (with host info) for functional and acceptance tests + # PLEASE ADJUST IT TO THE ACTUAL ENTRY SCRIPT URL + test_entry_url: http://localhost:8080/index-test.php diff --git a/tests/codeception/_bootstrap.php b/tests/codeception/_bootstrap.php index 011d783..9bbfcf9 100644 --- a/tests/codeception/_bootstrap.php +++ b/tests/codeception/_bootstrap.php @@ -1,35 +1,35 @@ - $testRoot]); -codecept_debug('Module root: ' . $testRoot); - -$humhubPath = getenv('HUMHUB_PATH'); -if ($humhubPath === false) { - // If no environment path was set, we assume residing in default the modules directory - $moduleConfig = require $testRoot . '/config/test.php'; - if (isset($moduleConfig['humhub_root'])) { - $humhubPath = $moduleConfig['humhub_root']; - } else { - $humhubPath = dirname(__DIR__, 5); - } -} - -\Codeception\Configuration::append(['humhub_root' => $humhubPath]); -codecept_debug('HumHub Root: ' . $humhubPath); - -// Load test configuration (/config/test.php or /config/env//test.php -$globalConfig = require $humhubPath . '/protected/humhub/tests/codeception/_loadConfig.php'; - -// Load default test bootstrap (initialize Yii...) -require $globalConfig['humhub_root'] . '/protected/humhub/tests/codeception/_bootstrap.php'; + $testRoot]); +codecept_debug('Module root: ' . $testRoot); + +$humhubPath = getenv('HUMHUB_PATH'); +if ($humhubPath === false) { + // If no environment path was set, we assume residing in default the modules directory + $moduleConfig = require $testRoot . '/config/test.php'; + if (isset($moduleConfig['humhub_root'])) { + $humhubPath = $moduleConfig['humhub_root']; + } else { + $humhubPath = dirname(__DIR__, 5); + } +} + +\Codeception\Configuration::append(['humhub_root' => $humhubPath]); +codecept_debug('HumHub Root: ' . $humhubPath); + +// Load test configuration (/config/test.php or /config/env//test.php +$globalConfig = require $humhubPath . '/protected/humhub/tests/codeception/_loadConfig.php'; + +// Load default test bootstrap (initialize Yii...) +require $globalConfig['humhub_root'] . '/protected/humhub/tests/codeception/_bootstrap.php'; diff --git a/tests/codeception/_output/.gitignore b/tests/codeception/_output/.gitignore index 44c5ea8..86d0cb2 100644 --- a/tests/codeception/_output/.gitignore +++ b/tests/codeception/_output/.gitignore @@ -1,4 +1,4 @@ -# Ignore everything in this directory -* -# Except this file +# Ignore everything in this directory +* +# Except this file !.gitignore \ No newline at end of file diff --git a/tests/codeception/_support/AcceptanceTester.php b/tests/codeception/_support/AcceptanceTester.php index 2668ee6..1349106 100644 --- a/tests/codeception/_support/AcceptanceTester.php +++ b/tests/codeception/_support/AcceptanceTester.php @@ -7,6 +7,9 @@ namespace questions; +use humhub\modules\content\components\ContentContainerActiveRecord; +use humhub\modules\questions\models\Question; + /** * Inherited Methods * @method void wantToTest($text) @@ -26,7 +29,84 @@ class AcceptanceTester extends \AcceptanceTester { use _generated\AcceptanceTesterActions; - /** - * Define custom actions here - */ + public function createQuestion(string $headline, string $description) + { + $this->amGoingTo('create a Question'); + $this->waitForText('Q&A'); + $this->click( 'Q&A', '#contentFormMenu'); + $this->waitForElementVisible('input[name="Question[question]"]'); + $this->fillField('Question[question]', $headline); + $this->fillField('#question-description .humhub-ui-richtext', $description); + $this->jsClick('#post_submit_button'); + + $this->waitForText($headline, null, '.wall-entry-header'); + $this->see('Provide an answer', '[data-content-component="questions.Question"]'); + $this->see('View all answers', '[data-content-component="questions.Question"]'); + } + + public function provideAnswer(string $answerText) + { + $this->waitForText('Provide an answer', null, '.field-questionanswer-answer'); + $this->fillField('#answerRichTextField0 .humhub-ui-richtext', $answerText); + $this->click('Save', '.questions-answer-form'); + $this->waitForText($answerText, null, '.except-best-answers'); + } + + private function getVoteButtonSelector(int $answerId, string $suffix = ''): string + { + return '[data-answer="' . $answerId . '"] [data-action-click="vote"]' . $suffix; + } + + public function canVote(int $answerId) + { + $this->seeElement($this->getVoteButtonSelector($answerId, ':not([disabled])')); + } + + public function cannotVote(int $answerId) + { + $this->seeElement($this->getVoteButtonSelector($answerId, '[disabled]')); + } + + public function vote(int $answerId, string $buttonTitle) + { + $this->canVote($answerId); + $buttonSelector = $this->getVoteButtonSelector($answerId, '[data-original-title="' . $buttonTitle . '"]'); + $this->jsClick($buttonSelector); + $this->waitForElementVisible($buttonSelector . '.active'); + } + + public function upVote(int $answerId) + { + $this->vote($answerId, 'Upvote'); + } + + public function downVote(int $answerId) + { + $this->vote($answerId, 'Downvote'); + } + + public function checkVotingSummary(int $answerId, int $summary) + { + $this->see($summary, '[data-answer="' . $answerId . '"] .questions-answer-voting div'); + } + + public function selectBestAnswer(int $answerId) + { + $answerSelector = '[data-answer="' . $answerId . '"]'; + $this->moveMouseOver(['css' => $answerSelector]); + $bestButtonSelector = '[data-action-click="best"]'; + $this->waitForElementVisible($bestButtonSelector); + $this->jsClick($answerSelector . ' ' . $bestButtonSelector); + $this->waitForElementVisible($answerSelector . '.questions-best-answer'); + } + + public function unselectBestAnswer() + { + $this->waitForElementVisible('.questions-best-answer'); + $bestButtonSelector = '[data-action-click="best"]'; + $this->waitForElementVisible($bestButtonSelector); + $this->jsClick('.questions-best-answer ' . $bestButtonSelector); + $this->wait(1); + $this->dontSeeElement('.questions-best-answer'); + } } diff --git a/tests/codeception/_support/_generated/.gitignore b/tests/codeception/_support/_generated/.gitignore index 44c5ea8..86d0cb2 100644 --- a/tests/codeception/_support/_generated/.gitignore +++ b/tests/codeception/_support/_generated/.gitignore @@ -1,4 +1,4 @@ -# Ignore everything in this directory -* -# Except this file +# Ignore everything in this directory +* +# Except this file !.gitignore \ No newline at end of file diff --git a/tests/codeception/acceptance.suite.yml b/tests/codeception/acceptance.suite.yml index 82bc91f..132904e 100644 --- a/tests/codeception/acceptance.suite.yml +++ b/tests/codeception/acceptance.suite.yml @@ -1,25 +1,25 @@ -# Codeception Test Suite Configuration - -# suite for acceptance tests. -# perform tests in browser using the Selenium-like tools. -# powered by Mink (http://mink.behat.org). -# (tip: that's what your customer will see). -# (tip: test your ajax and javascript by one of Mink drivers). - -# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. - -class_name: AcceptanceTester -modules: - enabled: - - WebDriver - - tests\codeception\_support\WebHelper - - tests\codeception\_support\DynamicFixtureHelper - config: - WebDriver: - url: 'http://localhost:8080/' - browser: chrome - restart: true - port: 4444 - capabilities: - chromeOptions: +# Codeception Test Suite Configuration + +# suite for acceptance tests. +# perform tests in browser using the Selenium-like tools. +# powered by Mink (http://mink.behat.org). +# (tip: that's what your customer will see). +# (tip: test your ajax and javascript by one of Mink drivers). + +# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. + +class_name: AcceptanceTester +modules: + enabled: + - WebDriver + - tests\codeception\_support\WebHelper + - tests\codeception\_support\DynamicFixtureHelper + config: + WebDriver: + url: 'http://localhost:8080/' + browser: chrome + restart: true + port: 4444 + capabilities: + chromeOptions: args: ["--lang=en-US"] \ No newline at end of file diff --git a/tests/codeception/acceptance/QuestionCest.php b/tests/codeception/acceptance/QuestionCest.php index b71cfa6..69acc8f 100644 --- a/tests/codeception/acceptance/QuestionCest.php +++ b/tests/codeception/acceptance/QuestionCest.php @@ -1,45 +1,69 @@ -wantTo('create a Question from stream'); - $I->amAdmin(); - - $I->amGoingTo('install the questions module for space 1'); - $I->enableModule(1, 'questions'); - $I->amOnSpace1(); - - $I->amGoingTo('create a Question'); - $I->waitForText('Q&A'); - $I->click( 'Q&A', '#contentFormMenu'); - $I->waitForElementVisible('input[name="Question[question]"]'); - $I->fillField('Question[question]', 'Question headline text?'); - $I->fillField('#question-description .humhub-ui-richtext', 'Question description text.'); - $I->jsClick('#post_submit_button'); - - $I->waitForText('Question headline text?', null, '.wall-entry-header'); - $I->see('Provide an answer', '[data-content-component="questions.Question"]'); - $I->see('View all answers (0)', '[data-content-component="questions.Question"]'); - - $I->amGoingTo('provide an Answer'); - $I->click('Provide an answer'); - $I->switchToNextTab(); - $I->waitForText('Collapse all answers (0)'); - $I->fillField('#answerRichTextField0 .humhub-ui-richtext', 'Answer text.'); - $I->click('Save', '.questions-answer-form'); - $I->waitForText('Answer text.', null, '.except-best-answers'); - } - -} +wantTo('create a Question from stream'); + $I->amAdmin(); + + $I->amGoingTo('install the questions module for space 1'); + $I->enableModule(1, 'questions'); + $I->amOnSpace1(); + + $I->createQuestion('Question headline text?', 'Question description text.'); + + $I->amGoingTo('provide first Answer from Admin'); + $I->click('Provide an answer'); + $I->switchToNextTab(); + $I->provideAnswer('First answer text from Admin.'); + $I->cannotVote(1); + + $I->amUser2(true); + $I->amOnSpace1(); + + $I->amGoingTo('provide first Answer from Sara'); + $I->waitForText('Provide an answer', null, '.wall-entry'); + $I->click('Provide an answer'); + $I->switchToNextTab(); + $I->provideAnswer('Second answer text from Sara.'); + $I->cannotVote(2); + + $I->amGoingTo('vote on the first Answer of Admin'); + $I->upVote(1); + $I->checkVotingSummary(1, 1); + $I->downVote(1); + $I->checkVotingSummary(1, -1); + + $I->amAdmin(true); + $I->amOnSpace1(); + + $I->waitForText('View all answers (2)', null, '.wall-entry'); + $I->click('View all answers (2)'); + $I->switchToNextTab(); + + $I->amGoingTo('vote on the second Answer by Admin'); + $I->upVote(2); + $I->checkVotingSummary(2, 1); + $I->wait(1); + $I->upVote(2); + $I->checkVotingSummary(2, 0); + + $I->amGoingTo('select the best Answer'); + $I->selectBestAnswer(2); + $I->unselectBestAnswer(); + $I->selectBestAnswer(1); + $I->selectBestAnswer(2); + } + +} diff --git a/tests/codeception/acceptance/_bootstrap.php b/tests/codeception/acceptance/_bootstrap.php index c44d23d..63fd3e0 100644 --- a/tests/codeception/acceptance/_bootstrap.php +++ b/tests/codeception/acceptance/_bootstrap.php @@ -1,6 +1,6 @@ - ['questions'], - 'fixtures' => [ - 'default', - 'question' => QuestionFixture::class, - ] -]; + ['questions'], + 'fixtures' => [ + 'default', + 'question' => QuestionFixture::class, + ] +]; diff --git a/tests/config/unit.php b/tests/config/unit.php index c519ed4..ae7fa3f 100644 --- a/tests/config/unit.php +++ b/tests/config/unit.php @@ -1,5 +1,5 @@ -