Skip to content

Commit c997129

Browse files
committed
Test Symfony Constraints
1 parent 09921b3 commit c997129

18 files changed

+2362
-899
lines changed

.github/workflows/symfony.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
strategy:
1919
fail-fast: true
2020
matrix:
21-
php-versions: ['8.1', '8.2', '8.3']
21+
php-versions: ['8.1', '8.2', '8.3', '8.4']
2222
steps:
2323
- name: Checkout
2424
uses: actions/checkout@v3

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"symfony/flex": "^1.17",
2323
"symfony/form": "5.4.*",
2424
"symfony/framework-bundle": "5.4.*",
25+
"symfony/http-client": "5.4.*",
2526
"symfony/mailer": "5.4.*",
2627
"symfony/monolog-bundle": "^3.7",
2728
"symfony/runtime": "5.4.*",

composer.lock

+1,826-869
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/packages/test/framework.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717

1818
// Web Profiler
1919
$framework->profiler([
20-
'collect' => false
20+
'collect' => false,
2121
]);
2222
};

config/routes.php

+60
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
declare(strict_types=1);
44

5+
use App\Controller\BrowserController;
56
use App\Controller\DashboardController;
7+
use App\Controller\DomCrawlerController;
8+
use App\Controller\FormController;
69
use App\Controller\HomeController;
10+
use App\Controller\HttpClientController;
711
use App\Controller\RegistrationController;
812
use App\Controller\SecurityController;
913
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
@@ -28,4 +32,60 @@
2832
$routes->add('app_register', '/register')
2933
->controller(RegistrationController::class)
3034
->methods(['GET', 'POST']);
35+
36+
$routes->add('app_browser_request_attr', '/request_attr')
37+
->controller([BrowserController::class, 'requestWithAttribute'])
38+
->methods(['GET']);
39+
40+
$routes->add('app_browser_response_cookie', '/response_cookie')
41+
->controller([BrowserController::class, 'responseWithCookie'])
42+
->methods(['GET']);
43+
44+
$routes->add('app_browser_response_json', '/response_json')
45+
->controller([BrowserController::class, 'responseJsonFormat'])
46+
->methods(['GET']);
47+
48+
$routes->add('app_browser_unprocessable_entity', '/unprocessable_entity')
49+
->controller([BrowserController::class, 'unprocessableEntity'])
50+
->methods(['GET']);
51+
52+
$routes->add('app_browser_redirect_home', '/redirect_home')
53+
->controller([BrowserController::class, 'redirectToHome'])
54+
->methods(['GET']);
55+
56+
$routes->add('app_dom_crawler_test_page', '/test_page')
57+
->controller(DomCrawlerController::class)
58+
->methods(['GET']);
59+
60+
$routes->add('app_form_test', '/test_form')
61+
->controller(FormController::class)
62+
->methods(['GET', 'POST']);
63+
64+
$routes->add('route_using_http_client', '/route-using-http-client')
65+
->controller([HttpClientController::class, 'routeUsingHttpClient'])
66+
->methods(['GET']);
67+
68+
$routes->add('internal_endpoint', '/internal-endpoint')
69+
->controller([HttpClientController::class, 'internalEndpoint'])
70+
->methods(['GET']);
71+
72+
$routes->add('route_making_multiple_requests', '/route-making-multiple-requests')
73+
->controller([HttpClientController::class, 'routeMakingMultipleRequests'])
74+
->methods(['GET']);
75+
76+
$routes->add('internal_endpoint_post', '/internal-endpoint-post')
77+
->controller([HttpClientController::class, 'internalEndpointPost'])
78+
->methods(['POST']);
79+
80+
$routes->add('route_should_not_make_specific_request', '/route-should-not-make-specific-request')
81+
->controller([HttpClientController::class, 'routeShouldNotMakeSpecificRequest'])
82+
->methods(['GET']);
83+
84+
$routes->add('internal_endpoint_not_desired', '/internal-endpoint-not-desired')
85+
->controller([HttpClientController::class, 'internalEndpointNotDesired'])
86+
->methods(['GET']);
87+
88+
$routes->add('send_email', '/send-email')
89+
->controller(App\Controller\SendEmailController::class)
90+
->methods(['GET']);
3191
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{% extends 'layout.html.twig' %}
2+
3+
{% block body %}
4+
<h1>{{ title }}</h1>
5+
6+
<label for="exampleCheckbox">Example Checkbox</label>
7+
<input type="checkbox" id="exampleCheckbox" name="exampleCheckbox" {% if checked %}checked{% endif %}>
8+
9+
<label for="exampleInput">Example Input</label>
10+
<input type="text" id="exampleInput" name="exampleInput" value="{{ inputValue }}">
11+
12+
<p class="info">This is a test paragraph with some text.</p>
13+
14+
<form id="testForm" action="{{ path('app_form_test') }}" method="post">
15+
<div>
16+
<label for="username">Username</label>
17+
<input type="text" id="username" name="username" value="{{ usernameValue }}">
18+
</div>
19+
<button type="submit">Submit</button>
20+
</form>
21+
{% endblock %}

src/Controller/BrowserController.php

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
8+
use Symfony\Component\HttpFoundation\Cookie;
9+
use Symfony\Component\HttpFoundation\RedirectResponse;
10+
use Symfony\Component\HttpFoundation\Request;
11+
use Symfony\Component\HttpFoundation\Response;
12+
13+
final class BrowserController extends AbstractController
14+
{
15+
public function requestWithAttribute(Request $request): Response
16+
{
17+
$request->attributes->set('page', 'register');
18+
19+
return $this->render('blog/home.html.twig');
20+
}
21+
22+
public function responseWithCookie(): Response
23+
{
24+
$response = new Response('TESTCOOKIE has been set.');
25+
$response->headers->setCookie(new Cookie('TESTCOOKIE', 'codecept'));
26+
27+
return $response;
28+
}
29+
30+
public function responseJsonFormat(): Response
31+
{
32+
return $this->json([
33+
'status' => 'success',
34+
'message' => "Expected format: 'json'.",
35+
]);
36+
}
37+
38+
public function unprocessableEntity(): Response
39+
{
40+
return $this->json([
41+
'status' => 'error',
42+
'message' => 'The request was well-formed but could not be processed.',
43+
], Response::HTTP_UNPROCESSABLE_ENTITY);
44+
}
45+
46+
public function redirectToHome(): RedirectResponse
47+
{
48+
return $this->redirectToRoute('index');
49+
}
50+
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
8+
use Symfony\Component\HttpFoundation\Response;
9+
10+
final class DomCrawlerController extends AbstractController
11+
{
12+
public function __invoke(): Response
13+
{
14+
return $this->render('dom_crawler/test_page.html.twig', [
15+
'page_title' => 'Test Page',
16+
'title' => 'Test Page',
17+
'checked' => true,
18+
'inputValue' => 'Expected Value',
19+
'usernameValue' => '',
20+
]);
21+
}
22+
}

src/Controller/FormController.php

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
8+
use Symfony\Component\HttpFoundation\Request;
9+
use Symfony\Component\HttpFoundation\Response;
10+
11+
final class FormController extends AbstractController
12+
{
13+
public function __invoke(Request $request): Response
14+
{
15+
$data = [
16+
'page_title' => 'Test Page',
17+
'checked' => false,
18+
'inputValue' => '',
19+
];
20+
if ($request->isMethod('POST')) {
21+
$data['usernameValue'] = $request->request->get('username', '');
22+
$data['title'] = 'Form Sent';
23+
} else {
24+
$data['usernameValue'] = 'codeceptUser';
25+
$data['title'] = 'Test Page';
26+
}
27+
28+
return $this->render('dom_crawler/test_page.html.twig', $data);
29+
}
30+
}
+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
8+
use Symfony\Component\HttpFoundation\Request;
9+
use Symfony\Component\HttpFoundation\Response;
10+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
11+
use Symfony\Contracts\HttpClient\HttpClientInterface;
12+
13+
final class HttpClientController extends AbstractController
14+
{
15+
private HttpClientInterface $httpClient;
16+
17+
public function __construct(HttpClientInterface $httpClient)
18+
{
19+
$this->httpClient = $httpClient;
20+
}
21+
22+
public function routeUsingHttpClient(): Response
23+
{
24+
$internalUrl = $this->generateUrl('internal_endpoint', [], UrlGeneratorInterface::ABSOLUTE_URL);
25+
26+
$response = $this->httpClient->request('GET', $internalUrl, [
27+
'headers' => ['Accept' => 'application/json'],
28+
]);
29+
30+
return new Response("Internal request completed successfully: {$response->getStatusCode()}");
31+
}
32+
33+
public function internalEndpoint(): Response
34+
{
35+
return $this->json(['message' => 'Response from internal endpoint.']);
36+
}
37+
38+
public function routeMakingMultipleRequests(): Response
39+
{
40+
$internalUrl = $this->generateUrl('internal_endpoint', [], UrlGeneratorInterface::ABSOLUTE_URL);
41+
$internalUrlPost = $this->generateUrl('internal_endpoint_post', [], UrlGeneratorInterface::ABSOLUTE_URL);
42+
43+
$response1 = $this->httpClient->request('GET', $internalUrl, [
44+
'headers' => ['Accept' => 'application/json'],
45+
]);
46+
47+
$response2 = $this->httpClient->request('POST', $internalUrlPost, [
48+
'headers' => ['Content-Type' => 'application/json'],
49+
'json' => ['key' => 'value'],
50+
]);
51+
52+
$response3 = $this->httpClient->request('GET', $internalUrl, [
53+
'headers' => ['Accept' => 'application/json'],
54+
]);
55+
56+
$message = sprintf(
57+
"Request 1: %d\nRequest 2: %d\nRequest 3: %d",
58+
$response1->getStatusCode(),
59+
$response2->getStatusCode(),
60+
$response3->getStatusCode()
61+
);
62+
63+
return new Response($message);
64+
}
65+
66+
public function internalEndpointPost(Request $request): Response
67+
{
68+
$data = json_decode($request->getContent(), true);
69+
70+
return $this->json(['received' => $data]);
71+
}
72+
73+
public function routeShouldNotMakeSpecificRequest(): Response
74+
{
75+
return new Response('No specific internal requests were made.');
76+
}
77+
78+
public function internalEndpointNotDesired(): Response
79+
{
80+
return $this->json(['message' => 'This endpoint should not be called.']);
81+
}
82+
}
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use App\Entity\User;
8+
use App\Utils\Mailer;
9+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
10+
use Symfony\Component\HttpFoundation\JsonResponse;
11+
use Symfony\Component\HttpFoundation\Response;
12+
13+
final class SendEmailController extends AbstractController
14+
{
15+
public function __construct(
16+
private readonly Mailer $mailer,
17+
) {
18+
}
19+
20+
public function __invoke(): Response
21+
{
22+
$user = new User();
23+
$user->setEmail('[email protected]');
24+
25+
$this->mailer->sendConfirmationEmail($user);
26+
27+
return new JsonResponse(['message' => 'Email sent successfully'], Response::HTTP_OK);
28+
}
29+
}

src/Utils/Mailer.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function __construct(private MailerInterface $mailer)
1818
public function sendConfirmationEmail(User $user): TemplatedEmail
1919
{
2020
$email = (new TemplatedEmail())
21-
21+
->from(new Address('[email protected]', 'No Reply'))
2222
->to(new Address($user->getEmail()))
2323
->subject('Account created successfully')
2424
->attach('Example attachment')

0 commit comments

Comments
 (0)