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/views.view.blog.yml b/config/install/views.view.blog.yml deleted file mode 100644 index 783846f..0000000 --- a/config/install/views.view.blog.yml +++ /dev/null @@ -1,228 +0,0 @@ -langcode: en -status: true -dependencies: - config: - - node.type.article - module: - - node - - user -id: blog -label: Blog -module: views -description: '' -tag: '' -base_table: node_field_data -base_field: nid -core: 8.x -display: - default: - display_plugin: default - id: default - display_title: Master - position: 0 - display_options: - access: - type: perm - options: - perm: 'access content' - cache: - type: tag - options: { } - query: - type: views_query - options: - disable_sql_rewrite: false - distinct: false - replica: false - query_comment: '' - query_tags: { } - exposed_form: - type: basic - options: - submit_button: Apply - reset_button: false - reset_button_label: Reset - exposed_sorts_label: 'Sort by' - expose_sort_order: true - sort_asc_label: Asc - sort_desc_label: Desc - pager: - type: mini - options: - items_per_page: 10 - offset: 0 - id: 0 - total_pages: null - expose: - items_per_page: false - items_per_page_label: 'Items per page' - items_per_page_options: '5, 10, 25, 50' - items_per_page_options_all: false - items_per_page_options_all_label: '- All -' - offset: false - offset_label: Offset - tags: - previous: ‹‹ - next: ›› - style: - type: default - options: - grouping: { } - row_class: '' - default_row_class: true - uses_fields: false - row: - type: fields - options: - inline: { } - separator: '' - hide_empty: false - default_field_elements: true - fields: - title: - id: title - table: node_field_data - field: title - entity_type: node - entity_field: title - label: '' - alter: - alter_text: false - make_link: false - absolute: false - trim: false - word_boundary: false - ellipsis: false - strip_tags: false - html: false - hide_empty: false - empty_zero: false - settings: - link_to_entity: true - plugin_id: field - relationship: none - group_type: group - admin_label: '' - exclude: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_alter_empty: true - click_sort_column: value - type: string - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - filters: - status: - value: '1' - table: node_field_data - field: status - plugin_id: boolean - entity_type: node - entity_field: status - id: status - 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 - 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: { } - relationships: { } - arguments: { } - display_extenders: { } - cache_metadata: - max-age: -1 - contexts: - - 'languages:language_content' - - 'languages:language_interface' - - url.query_args - - 'user.node_grants:view' - - user.permissions - tags: { } - page_1: - display_plugin: page - id: page_1 - display_title: Page - position: 1 - display_options: - display_extenders: { } - path: blog - cache_metadata: - max-age: -1 - contexts: - - '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 53% rename from tdd_blog.info.yml rename to tdd_dublin.info.yml index 1cdb6c0..4698633 100644 --- a/tdd_blog.info.yml +++ b/tdd_dublin.info.yml @@ -1,9 +1,4 @@ -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: - - drupal:node - - drupal:views 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)); - } - -}