Compare commits

..

No commits in common. "8.x-1.x" and "1-pass" have entirely different histories.

9 changed files with 56 additions and 212 deletions

1
.gitignore vendored
View file

@ -1 +0,0 @@
composer.lock

View file

@ -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

View file

@ -1,4 +0,0 @@
{
"name": "drupal/tdd_blog",
"type": "drupal-custom-module"
}

View file

@ -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

View file

@ -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

View file

@ -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: { }

View file

@ -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:

View file

@ -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);
}
}

View file

@ -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));
}
}