Skip to content

Commit 239ae07

Browse files
retlehsQWp6t
andauthored
✅ Add routing integration tests (#422)
Co-authored-by: QWp6t <hi@qwp6t.me>
1 parent 88096b5 commit 239ae07

File tree

7 files changed

+204
-5
lines changed

7 files changed

+204
-5
lines changed

.devcontainer/Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
1515
mariadb-client \
1616
vim \
1717
zip \
18+
wget \
1819
&& apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
1920

2021
# Install PHP extensions
@@ -36,9 +37,9 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
3637
pdo \
3738
pdo_mysql \
3839
zip \
39-
&& pecl install imagick-3.7.0 && docker-php-ext-enable imagick \
40+
# && pecl install imagick-3.7.0 && docker-php-ext-enable imagick \ # https://github.com/Imagick/imagick/issues/689
4041
&& pecl install -o -f redis && docker-php-ext-enable redis \
41-
&& pecl install xdebug-3.3.1 && docker-php-ext-enable xdebug \
42+
&& pecl install xdebug-3.4.0 && docker-php-ext-enable xdebug \
4243
&& apt-get -y autoremove && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
4344

4445
# Install composer

.devcontainer/config/web/default.conf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
server {
22
listen 80 default;
33
listen [::]:80;
4+
listen 8080 default_server;
5+
listen [::]:8080 default_server;
46

57
# listen 443 ssl;
68
# listen [::]:443 ssl ipv6only=on;
@@ -11,7 +13,7 @@ server {
1113
add_header X-Content-Type-Options "nosniff";
1214
charset utf-8;
1315

14-
server_name web.local web;
16+
server_name _;
1517
root /roots/app/public;
1618
index index.php index.html;
1719

.devcontainer/docker-compose.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ services:
55
build:
66
context: .
77
dockerfile: Dockerfile
8-
image: roots/dev-8.3
8+
image: roots/dev-8.4
99
extra_hosts:
1010
- 'host.docker.internal:host-gateway'
1111
environment:
@@ -29,6 +29,9 @@ services:
2929
image: nginx:latest
3030
ports:
3131
- '${FORWARD_WEB_PORT:-8080}:80'
32+
33+
expose:
34+
- '8080'
3235
environment:
3336
- NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE=1
3437
volumes:

.github/workflows/integration.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Integration
2+
3+
on: [push, pull_request, workflow_dispatch]
4+
5+
jobs:
6+
test:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v4
10+
11+
- name: Copy .env file
12+
working-directory: .devcontainer
13+
run: cp config/app/.env.example .env
14+
15+
- name: Start dev container and test
16+
uses: devcontainers/ci@v0.3
17+
with:
18+
configFile: .devcontainer/devcontainer.json
19+
runCmd: |
20+
cd /roots/app
21+
composer install
22+
# ???
23+
composer remove roots/acorn
24+
composer require roots/acorn --no-interaction
25+
composer require --dev nunomaduro/collision
26+
composer require --dev spatie/laravel-ignition
27+
# ???
28+
while ! mysqladmin ping -h"database" --silent; do
29+
sleep 1
30+
done
31+
wp core install --url=http://web:8080 --title=Acorn --admin_user=admin --admin_password=admin --admin_email=admin@example.com --skip-email --allow-root
32+
wp acorn optimize:clear
33+
34+
cd /roots/acorn
35+
composer install
36+
composer run-script test tests/Integration/Routing
37+
38+
- name: Verify routes
39+
run: |
40+
curl -s http://localhost:8080/test/ | grep "Howdy"

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ jobs:
4747
run: composer run-script lint
4848

4949
- name: Execute the Composer test script
50-
run: composer run-script test
50+
run: composer test -- --exclude-group=integration
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
namespace Roots\Acorn\Tests\Integration\Routing;
4+
5+
use GuzzleHttp\Client;
6+
7+
uses(RoutingTestCase::class)->group('integration');
8+
9+
expect()->extend('toHaveBodyClass', function (string $class) {
10+
preg_match('/<body[^>]*class=["\']([^"\']*)["\']/', $this->value, $matches);
11+
expect($matches)->toHaveCount(2, 'No body tag with class attribute found');
12+
expect($matches[1])->toContain($class);
13+
14+
return $this;
15+
});
16+
17+
it('handles the test route', function () {
18+
$client = new Client([
19+
'verify' => false,
20+
]);
21+
22+
$response = $client->request('GET', 'http://web:8080/test/');
23+
expect($response->getStatusCode())->toBe(200);
24+
expect((string) $response->getBody())->toContain('Howdy');
25+
});
26+
27+
it('does not intercept WordPress admin routes', function () {
28+
$client = new Client([
29+
'verify' => false,
30+
'allow_redirects' => false,
31+
]);
32+
33+
$response = $client->request('GET', 'http://web:8080/wp/wp-admin/');
34+
expect($response->getStatusCode())->toBe(302);
35+
expect($response->getHeader('Location')[0])->toContain('wp-login.php');
36+
});
37+
38+
it('handles non-existent routes with 404', function () {
39+
$client = new Client([
40+
'verify' => false,
41+
'http_errors' => false,
42+
]);
43+
44+
$response = $client->request('GET', 'http://web:8080/non-existent-'.time());
45+
expect($response->getStatusCode())->toBe(404);
46+
expect((string) $response->getBody())->toContain('Page not found');
47+
expect((string) $response->getBody())->toHaveBodyClass('error404');
48+
});
49+
50+
it('handles default homepage', function () {
51+
$client = new Client([
52+
'verify' => false,
53+
]);
54+
55+
$response = $client->request('GET', 'http://web:8080/');
56+
expect($response->getStatusCode())->toBe(200);
57+
expect((string) $response->getBody())->toHaveBodyClass('home');
58+
});
59+
60+
it('handles WordPress REST API routes', function () {
61+
$client = new Client([
62+
'verify' => false,
63+
]);
64+
65+
$response = $client->request('GET', 'http://web:8080/wp-json/');
66+
expect($response->getStatusCode())->toBe(200);
67+
68+
$data = json_decode((string) $response->getBody(), true);
69+
expect($data)->toHaveKey('name');
70+
expect($data)->toHaveKey('url');
71+
});
72+
73+
it('handles WordPress search route', function () {
74+
$client = new Client([
75+
'verify' => false,
76+
]);
77+
78+
$response = $client->request('GET', 'http://web:8080/search/test/');
79+
expect($response->getStatusCode())->toBe(200);
80+
expect((string) $response->getBody())->toHaveBodyClass('search');
81+
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Roots\Acorn\Tests\Integration\Routing;
4+
5+
use Illuminate\Foundation\Testing\Concerns\MakesHttpRequests;
6+
use Mockery\Adapter\Phpunit\MockeryTestCase;
7+
use Roots\Acorn\Tests\Test\Concerns\SupportsGlobalStubs;
8+
use Roots\Acorn\Tests\Test\Concerns\SupportsScopedFixtures;
9+
10+
class RoutingTestCase extends MockeryTestCase
11+
{
12+
use MakesHttpRequests;
13+
use SupportsGlobalStubs;
14+
use SupportsScopedFixtures;
15+
16+
protected function setUp(): void
17+
{
18+
parent::setUp();
19+
$this->clearStubs();
20+
21+
// Ensure routes directory exists
22+
if (! is_dir('/roots/app/public/routes')) {
23+
mkdir('/roots/app/public/routes', 0777, true);
24+
}
25+
26+
// Create web.php routes file
27+
$webRoutes = <<<'PHP'
28+
<?php
29+
30+
use Illuminate\Support\Facades\Route;
31+
32+
Route::middleware(['web'])->group(function () {
33+
Route::get('/test', fn() => 'Howdy')->name('test');
34+
});
35+
PHP;
36+
37+
file_put_contents('/roots/app/public/routes/web.php', $webRoutes);
38+
39+
// Ensure mu-plugins directory exists
40+
if (! is_dir('/roots/app/public/content/mu-plugins')) {
41+
mkdir('/roots/app/public/content/mu-plugins', 0777, true);
42+
}
43+
44+
// Create or update the Acorn boot mu-plugin
45+
$bootPlugin = <<<'PHP'
46+
<?php
47+
/*
48+
Plugin Name: Acorn Boot
49+
*/
50+
51+
use Roots\Acorn\Application;
52+
use Roots\Acorn\Configuration\Exceptions;
53+
use Roots\Acorn\Configuration\Middleware;
54+
55+
add_action('after_setup_theme', function () {
56+
Application::configure()
57+
->withMiddleware(function (Middleware $middleware) {
58+
//
59+
})
60+
->withExceptions(function (Exceptions $exceptions) {
61+
//
62+
})
63+
->withRouting(
64+
web: '/roots/app/public/routes/web.php'
65+
)
66+
->boot();
67+
}, 0);
68+
PHP;
69+
70+
file_put_contents('/roots/app/public/content/mu-plugins/01-acorn-boot.php', $bootPlugin);
71+
}
72+
}

0 commit comments

Comments
 (0)