diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 2659611..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -composer.lock diff --git a/README.md b/README.md index dc05439..4125f53 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,16 @@ -# TDD Example Drupal 8 Blog Module +# TDD Dublin demo module -A demo module to accompany my [TDD - Test Driven Drupal][0] talk, originally for DrupalCamp +A demo module to accompany my [TDD Test Driven Drupal][0] talk at DrupalCamp Dublin 2017. -In order to see my workflow of writing comments first, converting them into -failing tests, and then writing the implementation code to make them pass, you -can see the [list of previous commits][1] and see each step taken, as well as -[the tags][2] that identify the commits when each failing test is added and -then subsequently passes. - ## Acceptance Criteria This module will be used to demonstrate how to take a test-driven approach to develop a module to the following acceptance criteria: - As a site visitor -- I want to see a list of all published blog posts at `/blog` -- Ordered by post date, with the newest posts first - -## Installation - -Within your Drupal 8 site: - -```bash -cd modules -git clone git@github.com:opdavies/drupal-module-tdd-blog.git tdd_blog -``` +- I want to see a list of all published pages at `/pages` +- Ordered alphabetically by title ## Running the Tests @@ -33,23 +18,23 @@ These tests are functional tests based on the `BrowserTestBase` class so need to be executed with PHPUnit (which is required in core's `composer.json` file). The path to your `vendor` directory may be different depending on your setup. -Because of autoloading, you will either need to be inside Drupal's `core` subdirectory -, or add `-c core` to the PHPUnit command when running the tests for them to execute successfully. +Because of autoloading, you will need to be inside Drupal's `core` subdirectory +when running the tests for them to execute successfully. This also assumes that the module is within a `modules/custom` directory and -named `tdd_blog` as per the repository name. +named `tdd_dublin` as per the repository name. ``` -vendor/bin/phpunit -c core modules/custom/tdd_blog +cd core + +../vendor/bin/phpunit ../modules/custom/tdd_dublin ``` You can use PHPUnit's `--filter` option to specify a single test method to run, rather than all of the tests within the module. For example: ``` -vendor/bin/phpunit -c core modules/custom/tdd_blog --filter=testOnlyPublishedPagesAreShown +../vendor/bin/phpunit ../modules/custom/tdd_dublin --filter=testOnlyPublishedPagesAreShown ``` [0]: https://www.oliverdavies.uk/talks/tdd-test-driven-drupal -[1]: https://github.com/opdavies/drupal-module-tdd-blog/commits/HEAD -[2]: https://github.com/opdavies/drupal-module-tdd-blog/tags diff --git a/composer.json b/composer.json deleted file mode 100644 index aa7e974..0000000 --- a/composer.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "drupal/tdd_blog", - "type": "drupal-custom-module" -} diff --git a/config/install/node.type.article.yml b/config/install/node.type.article.yml deleted file mode 100644 index 1fd439c..0000000 --- a/config/install/node.type.article.yml +++ /dev/null @@ -1,10 +0,0 @@ -langcode: en -status: true -dependencies: { } -name: Article -type: article -description: 'Use <em>articles</em> for time-sensitive content like news, press releases or blog posts.' -help: '' -new_revision: true -preview_mode: 1 -display_submitted: true diff --git a/config/install/node.type.page.yml b/config/install/node.type.page.yml new file mode 100644 index 0000000..a6ddd46 --- /dev/null +++ b/config/install/node.type.page.yml @@ -0,0 +1,12 @@ +langcode: en +status: true +dependencies: { } +_core: + default_config_hash: KuyA4NHPXcmKAjRtwa0vQc2ZcyrUJy6IlS2TAyMNRbc +name: 'Basic page' +type: page +description: 'Use <em>basic pages</em> for your static content, such as an ''About us'' page.' +help: '' +new_revision: true +preview_mode: 1 +display_submitted: false diff --git a/config/install/views.view.blog.yml b/config/install/views.view.pages.yml similarity index 73% rename from config/install/views.view.blog.yml rename to config/install/views.view.pages.yml index 783846f..bf293cd 100644 --- a/config/install/views.view.blog.yml +++ b/config/install/views.view.pages.yml @@ -1,13 +1,11 @@ langcode: en status: true dependencies: - config: - - node.type.article module: - - node - - user -id: blog -label: Blog + - node + - user +id: pages +label: pages module: views description: '' tag: '' @@ -138,62 +136,22 @@ display: expose: operator: '' group: 1 - type: - id: type - table: node_field_data - field: type - relationship: none - group_type: group - admin_label: '' - operator: in - value: - article: article - group: 1 - exposed: false - expose: - operator_id: '' - label: '' - description: '' - use_operator: false - operator: '' - identifier: '' - required: false - remember: false - multiple: false - remember_roles: - authenticated: authenticated - reduce: false - is_grouped: false - group_info: - label: '' - description: '' - identifier: '' - optional: true - widget: select - multiple: false - remember: false - default_group: All - default_group_multiple: { } - group_items: { } - entity_type: node - entity_field: type - plugin_id: bundle sorts: created: id: created table: node_field_data field: created + order: DESC + entity_type: node + entity_field: created + plugin_id: date relationship: none group_type: group admin_label: '' - order: ASC exposed: false expose: label: '' granularity: second - entity_type: node - entity_field: created - plugin_id: date header: { } footer: { } empty: { } @@ -203,11 +161,11 @@ display: cache_metadata: max-age: -1 contexts: - - 'languages:language_content' - - 'languages:language_interface' - - url.query_args - - 'user.node_grants:view' - - user.permissions + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions tags: { } page_1: display_plugin: page @@ -216,13 +174,13 @@ display: position: 1 display_options: display_extenders: { } - path: blog + path: pages cache_metadata: max-age: -1 contexts: - - 'languages:language_content' - - 'languages:language_interface' - - url.query_args - - 'user.node_grants:view' - - user.permissions + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions tags: { } diff --git a/tdd_blog.info.yml b/tdd_dublin.info.yml similarity index 75% rename from tdd_blog.info.yml rename to tdd_dublin.info.yml index 1cdb6c0..448351b 100644 --- a/tdd_blog.info.yml +++ b/tdd_dublin.info.yml @@ -1,7 +1,6 @@ -name: 'TDD Blog' +name: 'TDD Dublin' description: 'A demo module for DrupalCamp Dublin to show test driven module development.' core: 8.x -core_version_requirement: ^8 || ^9 type: module dependencies: diff --git a/tests/src/Functional/PageListTest.php b/tests/src/Functional/PageListTest.php index 6205de1..9c1d9e6 100644 --- a/tests/src/Functional/PageListTest.php +++ b/tests/src/Functional/PageListTest.php @@ -1,20 +1,24 @@ <?php -namespace Drupal\Tests\tdd_blog\Functional; +namespace Drupal\Tests\tdd_dublin\Functional; use Drupal\Tests\BrowserTestBase; -use Symfony\Component\HttpFoundation\Response; class PageListTest extends BrowserTestBase { - protected static $modules = ['tdd_blog']; + /** + * {@inheritdoc} + */ + protected static $modules = ['tdd_dublin']; - protected $defaultTheme = 'stark'; - - public function testBlogPageExists() { - $this->drupalGet('blog'); - - $this->assertSession()->statusCodeEquals(Response::HTTP_OK); + /** + * Test that the pages listing page exists and is accessible. + */ + public function testListingPageExists() { + // Go to /pages and check that it is accessible by checking the status + // code. + $this->drupalGet('pages'); + $this->assertSession()->statusCodeEquals(200); } } diff --git a/tests/src/Kernel/PageListTest.php b/tests/src/Kernel/PageListTest.php deleted file mode 100644 index 2e5cb48..0000000 --- a/tests/src/Kernel/PageListTest.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -namespace Drupal\Tests\tdd_blog\Kernel; - -use Drupal\Core\Datetime\DrupalDateTime; -use Drupal\KernelTests\Core\Entity\EntityKernelTestBase; -use Drupal\Tests\node\Traits\NodeCreationTrait; -use Drupal\views\ResultRow; - -/** - * @group tdd_blog - */ -class PageListTest extends EntityKernelTestBase { - - use NodeCreationTrait; - - /** - * {@inheritdoc} - */ - public static $modules = [ - 'node', - 'tdd_blog', - 'views', - ]; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - - $this->installEntitySchema('node'); - $this->installEntitySchema('user'); - - $this->installConfig(['filter', 'tdd_blog']); - } - - /** - * Ensure that only the correct nodes are returned. - * - * Ensure that only published pages are returned by the view. Unpublished - * pages or content of different types should not be shown. - */ - public function testOnlyPublishedArticlesAreShown() { - // This is a published article, so it should be visible. - $this->createNode(['type' => 'page', 'status' => TRUE]); - - // This is a page, so it should not be visible. - $this->createNode(['type' => 'article']); - - // This article is not published, so it should not be visible. - $this->createNode(['type' => 'article', 'status' => FALSE]); - - // Rather than testing the rendered HTML, we are going to load the view - // results programmatically and run assertions against the data it returns. - // This makes it easier to test certain scenarios, and ensures that the - // test is future-proofed and won't fail at a later date due to a change in - // the presentation code. - $nids = $this->getViewResults(); - - // Only node 1 matches the criteria of being a published page, so only that - // node ID should be being returned from the view. assertEquals() can be - // used to compare the expected result to what is being returned. - $this->assertEquals([2], $nids); - } - - /** - * Ensure that the results are ordered by title. - */ - public function testArticlesAreOrderedByDate() { - $this->createNode(['type' => 'article', 'created' => (new DrupalDateTime('+1 day'))->getTimestamp()]); - $this->createNode(['type' => 'article', 'created' => (new DrupalDateTime('+1 month'))->getTimestamp()]); - $this->createNode(['type' => 'article', 'created' => (new DrupalDateTime('+3 days'))->getTimestamp()]); - $this->createNode(['type' => 'article', 'created' => (new DrupalDateTime('+1 hour'))->getTimestamp()]); - - // Get the result data from the view. - $nids = $this->getViewResults(); - - // Compare the expected order based on the titles defined above to the - // ordered results from the view. - $this->assertEquals([4, 1, 3, 2], $nids); - } - - /** - * Load the view and get the results. - * - * @param string $view - * (optional) The name of the view. Defaults to 'blog'. - * - * @return array - * An array of returned entity IDs. - */ - private function getViewResults($view = 'blog') { - return array_map(function (ResultRow $result) { - return $result->_entity->id(); - }, views_get_view_result($view)); - } - -}