From e55c81ec7c7cd45b3a10aaff6c5076762764e36f Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Sat, 13 Nov 2021 20:33:35 +1300 Subject: [PATCH] MNT Add behat tests --- .github/workflows/main.yml | 11 ++ .travis.yml | 8 +- behat.yml | 29 +++++ composer.json | 3 +- tests/behat/_manifest_exclude | 0 tests/behat/features/blog.feature | 121 ++++++++++++++++++ tests/behat/files/file1.jpg | Bin 0 -> 2292 bytes tests/behat/src/FeatureContext.php | 105 +++++++++++++++ tests/behat/src/FixtureContext.php | 9 ++ tests/{ => php}/BlogCategoryTest.php | 0 tests/{ => php}/BlogFunctionalTest.php | 0 tests/{ => php}/BlogFunctionalTest.yml | 0 tests/{ => php}/BlogPostFilterTest.php | 0 tests/{ => php}/BlogPostNotificationsTest.php | 0 tests/{ => php}/BlogPostTest.php | 0 tests/{ => php}/BlogTagTest.php | 0 tests/{ => php}/BlogTagsCloudWidgetTest.php | 0 tests/{ => php}/BlogTest.php | 0 .../Model/BlogControllerFunctionalTest.php | 0 .../Model/BlogControllerFunctionalTest.yml | 0 .../Widgets/BlogArchiveWidgetTest.php | 0 .../Widgets/BlogArchiveWidgetTest.yml | 0 tests/{ => php}/blog.yml | 0 23 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 behat.yml create mode 100644 tests/behat/_manifest_exclude create mode 100644 tests/behat/features/blog.feature create mode 100644 tests/behat/files/file1.jpg create mode 100644 tests/behat/src/FeatureContext.php create mode 100644 tests/behat/src/FixtureContext.php rename tests/{ => php}/BlogCategoryTest.php (100%) rename tests/{ => php}/BlogFunctionalTest.php (100%) rename tests/{ => php}/BlogFunctionalTest.yml (100%) rename tests/{ => php}/BlogPostFilterTest.php (100%) rename tests/{ => php}/BlogPostNotificationsTest.php (100%) rename tests/{ => php}/BlogPostTest.php (100%) rename tests/{ => php}/BlogTagTest.php (100%) rename tests/{ => php}/BlogTagsCloudWidgetTest.php (100%) rename tests/{ => php}/BlogTest.php (100%) rename tests/{ => php}/Model/BlogControllerFunctionalTest.php (100%) rename tests/{ => php}/Model/BlogControllerFunctionalTest.yml (100%) rename tests/{ => php}/Widgets/BlogArchiveWidgetTest.php (100%) rename tests/{ => php}/Widgets/BlogArchiveWidgetTest.yml (100%) rename tests/{ => php}/blog.yml (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..f8e96e9 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,11 @@ +name: Module CI + +on: + push: + pull_request: + +jobs: + ci: + uses: silverstripe/github-actions-ci-cd/.github/workflows/ci.yml@0.1.11 + with: + run_endtoend: true diff --git a/.travis.yml b/.travis.yml index 785d9ea..53088ed 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,10 @@ version: ~> 1.0 import: - - silverstripe/silverstripe-travis-shared:config/provision/standard-jobs-range-npm.yml + - silverstripe/silverstripe-travis-shared:config/provision/standard-jobs-range-behat-npm.yml + +env: + global: + - COMPOSER_ROOT_VERSION=2.x-dev + # Required for behat testing + - REQUIRE_EXTRA="silverstripe/widgets:^2 silverstripe/comments:^3 silverstripe/content-widget:^2" diff --git a/behat.yml b/behat.yml new file mode 100644 index 0000000..0b699a4 --- /dev/null +++ b/behat.yml @@ -0,0 +1,29 @@ +default: + suites: + blog: + paths: + - "%paths.modules.blog%/tests/behat/features" + contexts: + - SilverStripe\Admin\Tests\Behat\Context\AdminContext + - SilverStripe\BehatExtension\Context\BasicContext + - SilverStripe\BehatExtension\Context\EmailContext + - SilverStripe\BehatExtension\Context\LoginContext + - SilverStripe\Framework\Tests\Behaviour\CmsFormsContext + - SilverStripe\Framework\Tests\Behaviour\CmsUiContext + - SilverStripe\Blog\Tests\Behat\Context\FeatureContext + - SilverStripe\Blog\Tests\Behat\Context\FixtureContext + - + SilverStripe\Blog\Tests\Behat\Context\FixtureContext: + - "%paths.modules.blog%/tests/behat/files/" + + extensions: + SilverStripe\BehatExtension\MinkExtension: + default_session: facebook_web_driver + javascript_session: facebook_web_driver + facebook_web_driver: + browser: chrome + wd_host: "http://127.0.0.1:9515" + + SilverStripe\BehatExtension\Extension: + screenshot_path: "%paths.base%/artifacts/screenshots" + bootstrap_file: vendor/silverstripe/framework/tests/behat/serve-bootstrap.php diff --git a/composer.json b/composer.json index 7db9426..bd21920 100755 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "autoload": { "psr-4": { "SilverStripe\\Blog\\": "src/", - "SilverStripe\\Blog\\Tests\\": "tests/" + "SilverStripe\\Blog\\Tests\\": "tests/php/", + "SilverStripe\\Blog\\Tests\\Behat\\Context\\": "tests/behat/src/" } }, "license": "BSD-2-Clause", diff --git a/tests/behat/_manifest_exclude b/tests/behat/_manifest_exclude new file mode 100644 index 0000000..e69de29 diff --git a/tests/behat/features/blog.feature b/tests/behat/features/blog.feature new file mode 100644 index 0000000..2630f27 --- /dev/null +++ b/tests/behat/features/blog.feature @@ -0,0 +1,121 @@ +Feature: Create a blog + As a website user + I want to create a blog + + Background: + Given the "group" "EDITOR group" has permissions "CMS_ACCESS_LeftAndMain" + And I add an extension "SilverStripe\Widgets\Extensions\WidgetPageExtension" to the "Page" class + And I add an extension "SilverStripe\Comments\Extensions\CommentsExtension" to the "Page" class + + Given I take a screenshot after every step + Given I dump the rendered HTML after every step + + And an "image" "Uploads/file1.jpg" + + # Login then logout to created member + And I am logged in with "EDITOR" permissions + And I go to "/Security/login" + And I press the "Log in as someone else" button + And I am logged in with "ADMIN" permissions + + # Create a new blog called "New Blog" + When I go to "/admin/pages" + And I press the "Add new" button + And I select the "Blog" radio button + And I press the "Create" button + + # Add widgets + And I click the "Widgets" CMS tab + And I uncheck "Inherit Sidebar From Parent" + And I add the "Content" widget + And I add the "Archive" widget + And I add the "Blog Tags" widget + And I fill in the "Content" widget field "Title" with "My content widget title" + And I fill in the "Content" widget HTML field "Content" with "

Content widget content

" + And I fill in the "Archive" widget field "Title" with "My archive widget title" + And I fill in the "Blog Tags" widget field "Title" with "My blog tags widget title" + And I press the "Save" button + + # Add EDITOR as an Editor + And I click the "Settings" CMS tab + And I click the "Users" CMS tab + And I select "EDITOR" from "Editors" + + # Publish and logout + And I press the "Publish" button + And I go to "/Security/login" + And I press the "Log in as someone else" button + + Scenario: Create a blog post + Given I log in with "EDITOR@example.org" and "Secret!123" + + # Create a new blog post called "New Post" + When I go to "/admin/pages" + And I follow "New Blog" + And I click the "Blog Posts" CMS tab + And I press the "Add new Blog Post" button + And I fill in "Post Title" with "New Post" + + # Add a "Featured image" + And I press the "Choose existing" button + + # Select file1.jpg - asset-admin FeatureContext is not available here so use css selector + And I click on the ".gallery__files .gallery-item" element + And I press the "Insert" button + + # Add categories and tags + And I click the "Post Options" CMS tab + And I add "My Category" to the "Categories" tag field + And I add "My Tag" to the "Tags" tag field + + # Publish the blog post + And I press the "Publish" button + + # Test the frontend + When I go to "/new-blog" + Then I should see "New Blog" + And I should see "New Post" + + # Widgets + And I should see "My content widget title" + And the rendered HTML should contain "

Content widget content

" + And I should see "My blog tags widget title" + + # Hyperlink to "New Post" + Then the rendered HTML should contain "href=\"/new-blog/new-post" + + # Category + And the rendered HTML should contain "href=\"/new-blog/category/my-category\"" + + # Tag + And the rendered HTML should contain "href=\"/new-blog/tag/my-tag\"" + + # Test that blog post shows in category view + When I go to "/new-blog/category/my-category" + Then I should see "New Post" + + # Test that blog post shows in tag view + When I go to "/new-blog/tag/my-tag" + Then I should see "New Post" + + # Commenting + When I fill in "Your name" with "My Name" + And I fill in "Email" with "hello@example.com" + And I fill in "Comments" with "My comments" + When I press the "Post" button + Then I should see "New Post" + + # Moderation + When I go to "/admin/pages" + And I follow "New Blog" + And I click the "Blog Posts" CMS tab + # Click on the first blog post + And I click on the ".col-Title" element + And I click the "Comments" CMS tab + Then I should see "Approved (1)" + When I click the "Approved (1)" CMS tab + Then I should see "hello@example.com" + When I click on the ".action-menu__toggle" element + And I press the "Spam" button + And I wait for 2 seconds + Then I should not see "hello@example.com" diff --git a/tests/behat/files/file1.jpg b/tests/behat/files/file1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..beb5a91b0aba93d3b54dadc12cff0104307d718e GIT binary patch literal 2292 zcmbV~c|6qJ9>;%UHjExS$z>*csbTDTlq4fO5~U_1OJm>1u4{=xiK_^q9w8LDu4RZU z8557($~v-CGowgKGnQ!>GxN;U>viux_m6w;=e)k(*IB;jygu)9j^K@e2FN&K9k2ih z1OOmm0|b2FS6eqbn=>wMhfslj2ScL#15xo9v>{3_E+#l45ar-#k8(U^XOD_EGun3m zMU3+e3yw`f9Y$H2N($xxTR;pXk|>Lb1ObaO6aoQ5U{DzBN5Cb-VQ>jJ3?_~cmyi@m z*pos?N{I%dLw;@*gMz_ONjMDtqvU@|f@grNIA8=Afk7I8m@Eh^3ldNOq!1GN!=8}z zr$Az02owev+CT^kNHRkEV6f0MROnb(og!QZAhJ-oy%-yqysIxV&@@|zq+B&*=`}UidnweWz9W@cqyyPi`}c)O^$RrQ0K+Pa62>RVddNbMa@I=jdNl;?v( ze+<7EpO~DYPQRI%r85>jd|X`mwEUU1w!X2+{?6Ij7IA?9@J}pZ{*PR;LM}1U8^A?e zAh85tfMp@jy%?CBjVs)jD6e6ZF0OFwR%LU)gr>0@Q}JT-n52@H30<2dLi<7X-+^WP zUu6FR`#0AtAO!{q9}g@GSOYtk7S!~}8_$uB+tPfA6|UScm#}l9_X_1u&tL^TQrcdj z>+Q>0tL3s|#Fe0ldmx9gHPI4kJ)~!b1g|z(yjN8XLXuJS` zbkD^*z5G3tsmzY%^l%+H!&dUleDZ1USK^@~9a{$<->ldybWF6F1{a6<+N$d#8AAgp zF*E@{=}DkRUa!e;;(^bU4KCsXbS(Fn>-RVSUwuF-0BsG#=yT*B;m`NAB6s9h`d>5U z*+I!zwFZ}WM9j}@ilS9JY$m9{% zsipE$tY6wzt5%oilB;$vxZ$B)^iwIL(cE|@3X!9 zbDTr53I6Tz7Vf2L?$z^&yIy=qePSj`q;Sh*>J)8~lG@3xHx8B!&?D3*4f z(16K+;)d7>XX`?zlMS|;WkY<4M_lzC8P1ia)Nya69S5E28twV6Tr)4-C%HIWYv;`p zTFU*5sQNAVW%oH)uPc)2`u@gP@{ucS0`FF`%&cKK#iMe(X=8+7xbU!S*y$YfG} zd!*;~%s9DPl~}k|wAj%YqC~`n?CF_g;&br>rUQqLThBn~X_7ouUO~4nSB>9a(PEyR zYQ=fM82>hyYA~Vx>0tfi*&?c+Ki5RkW%Z(S<%R3+=sK-?4c_)yg9C<->6uQuAmw+P z;wM73KYb_lJxGnY^I^(JN-JdXWKvPmD@={^;Mhq_QF-2Mi*u)0MeW*Q7fLY8e88IN z^iAG|>;KtsJ~5jw^VZJ5gK<0w(h{lU`qbdX1UyJtlhZtGsk?^cL-gmUr7TrLk#9c^FourW>LL;vTauCJy%?{X4MKQ47hT0+*~|arf=qg$=ZZpIf=5s9ayg_A#PN4J0T-0M|ZS11V(s}GqPVIYIU|8(Oode6acclYO}%9{6kE$M-OZo=C-yyXY&dv9s5YCdN`?_7VMjq_Tz_D9N2jX zzNGAes%lE4CzY=jq&&-;{#(iOONt{y(Z$;lRgq|eJwDf?YF;?+-#s=ml&N7?n6uuL zpVn4EF_<;__FFG&W&dz3x&Q30liRolrQ=!!#9c2b&2z2S2nX6%6as@lfIEU1*V(9j zzpO4?`p6JhBgZU%O|S6;>{IIPs}&x4_u)R5T+^5B6oBju%(2V%8aaBvvke7TJ0MLk F^Cu<`6}$id literal 0 HcmV?d00001 diff --git a/tests/behat/src/FeatureContext.php b/tests/behat/src/FeatureContext.php new file mode 100644 index 0000000..e656ff2 --- /dev/null +++ b/tests/behat/src/FeatureContext.php @@ -0,0 +1,105 @@ +getSession()->getPage(); + $h3s = $page->findAll('css', '.availableWidgetsHolder h3'); + $found = false; + foreach ($h3s as $h3) { + if ($h3->getText() !== $widgetTitle) { + continue; + } + $found = true; + $h3->click(); + } + Assert::assertTrue($found, "Widget {$widgetTitle} was not found"); + } + + /** + * Fills in a field within a widget + * + * @Then /^I fill in the "([^"]+)" widget field "([^"]+)" with "([^"]+)"$/ + * @param $widgetTitle e.g. "Content" + * @param $htmlFragment e.g. "Title" + * @param $value e.g. "Lorem ipsum" + */ + public function iFillInTheWidgetField($widgetTitle, $fieldTitle, $value) + { + $page = $this->getSession()->getPage(); + $widget = $this->getWidget($widgetTitle); + $field = $widget->findField($fieldTitle); + Assert::assertNotNull($field, "Widget field {$fieldTitle} was not found"); + $field->setValue($value); + } + + /** + * Adapated from framework CmsFormsContext stepIFillInTheHtmlFieldWith + * + * @When /^I fill in the "([^"]+)" widget HTML field "([^"]+)" with "([^"]+)"$/ + */ + public function stepIFillInTheHtmlFieldWith($widgetTitle, $fieldTitle, $value) + { + $widget = $this->getWidget($widgetTitle); + $field = $this->getDescendantHtmlField($widget, $fieldTitle); + $this->getSession()->evaluateScript(sprintf( + "jQuery('#%s').entwine('ss').getEditor().setContent('%s')", + $field->getAttribute('id'), + addcslashes($value, "'") + )); + $this->getSession()->evaluateScript(sprintf( + "jQuery('#%s').entwine('ss').getEditor().save()", + $field->getAttribute('id') + )); + } + + /** + * @return NodeElement|null + */ + private function getWidget($widgetTitle) + { + $ret = null; + $widgets = $this->getSession()->getPage()->findAll('css', '.usedWidgets .Widget'); + foreach ($widgets as $widget) { + $h3 = $widget->find('css', 'h3'); + if (!$h3 || $h3->getText() !== $widgetTitle) { + continue; + } + $ret = $widget; + break; + } + Assert::assertNotNull($ret, "Widget edit form for {$widgetTitle} was not found"); + return $ret; + } + + /** + * @param NodeElement $ancestor + * @param string $locator + * @return NodeElement|null + */ + private function getDescendantHtmlField($element, $locator) + { + $textarea = $element->find('css', "textarea.htmleditor[name='{$locator}']"); + if (is_null($textarea)) { + $labels = $element->findAll('xpath', "//label[contains(text(), '{$locator}')]"); + Assert::assertCount(1, $labels, "Found more than one html field label containing the phrase '{$locator}}'"); + $label = array_shift($labels); + $textarea = $element->find('css', '#' . $label->getAttribute('for')); + } + Assert::assertNotNull($textarea, "HTML field {$locator} not found"); + return $textarea; + } +} diff --git a/tests/behat/src/FixtureContext.php b/tests/behat/src/FixtureContext.php new file mode 100644 index 0000000..5940466 --- /dev/null +++ b/tests/behat/src/FixtureContext.php @@ -0,0 +1,9 @@ +