-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathSaveEntryTicketPrefixTest.php
More file actions
155 lines (126 loc) · 5.83 KB
/
Copy pathSaveEntryTicketPrefixTest.php
File metadata and controls
155 lines (126 loc) · 5.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php
/*
* Copyright (c) 2025-2026 Netresearch DTT GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
declare(strict_types=1);
namespace Tests\Controller;
use App\Entity\Project;
use Symfony\Component\HttpFoundation\Request;
use Tests\AbstractWebTestCase;
/**
* Ticket-prefix validation on /tracking/save (v4 parity, see #306).
*
* The project's jira_id is a comma-separated list of allowed prefixes
* (entries trimmed before comparison); the project's internal Jira project
* key is accepted as an alternative match; prefixes must match exactly,
* not merely be a string prefix of the ticket.
*
* @internal
*
* @coversNothing
*/
final class SaveEntryTicketPrefixTest extends AbstractWebTestCase
{
/**
* @param array<string, string|int> $overrides
*
* @return array<string, string|int>
*/
private function saveParameters(array $overrides = []): array
{
return $overrides + [
'start' => '09:00:00',
'end' => '10:00:00',
'date' => '2024-01-02',
'project_id' => 1,
'customer_id' => 1,
'activity_id' => 1,
];
}
private function configureProjectOne(?string $jiraId, ?string $internalKey = null, ?string $internalTicketSystem = null, ?string $subtickets = null): void
{
$container = $this->client->getContainer();
/** @var \Doctrine\Bundle\DoctrineBundle\Registry $doctrine */
$doctrine = $container->get('doctrine');
$em = $doctrine->getManager();
$project = $em->getRepository(Project::class)->find(1);
self::assertInstanceOf(Project::class, $project);
$project->setJiraId($jiraId);
if (null !== $internalKey) {
$project->setInternalJiraProjectKey($internalKey);
}
if (null !== $internalTicketSystem) {
$project->setInternalJiraTicketSystem($internalTicketSystem);
}
if (null !== $subtickets) {
$project->setSubtickets($subtickets);
}
$em->persist($project);
$em->flush();
}
public function testTicketMatchingSingleJiraIdIsAccepted(): void
{
$this->logInSession('unittest');
// Fixture project 1 has jira_id 'SA'
$this->client->request(Request::METHOD_POST, '/tracking/save', $this->saveParameters(['ticket' => 'SA-123']), [], ['HTTP_ACCEPT' => 'application/json']);
$this->assertStatusCode(200);
}
public function testTicketMatchingLaterPrefixInCommaListIsAccepted(): void
{
$this->logInSession('unittest');
$this->configureProjectOne('SA, DHLSUP');
$this->client->request(Request::METHOD_POST, '/tracking/save', $this->saveParameters(['ticket' => 'DHLSUP-123456']), [], ['HTTP_ACCEPT' => 'application/json']);
$this->assertStatusCode(200);
}
public function testTicketMatchingInternalJiraProjectKeyIsAccepted(): void
{
$this->logInSession('unittest');
$this->configureProjectOne('SA', 'OPSDHL', '1');
$this->client->request(Request::METHOD_POST, '/tracking/save', $this->saveParameters(['ticket' => 'OPSDHL-77']), [], ['HTTP_ACCEPT' => 'application/json']);
$this->assertStatusCode(200);
}
public function testTicketListedInSyncedSubticketsIsAcceptedDespiteForeignPrefix(): void
{
$this->logInSession('unittest');
// Project 1 allows only the 'SA' prefix, but its synced subtickets list
// enumerates a key from another Jira project — that exact key must be
// accepted (an epic subtask can live in a different project).
$this->configureProjectOne('SA', null, null, 'FOREIGN-9, FOREIGN-10');
$this->client->request(Request::METHOD_POST, '/tracking/save', $this->saveParameters(['ticket' => 'FOREIGN-9']), [], ['HTTP_ACCEPT' => 'application/json']);
$this->assertStatusCode(200);
}
public function testForeignPrefixTicketNotInSubticketsIsStillRejected(): void
{
$this->logInSession('unittest');
// A foreign key that is NOT in the subtickets list stays rejected.
$this->configureProjectOne('SA', null, null, 'FOREIGN-9');
$this->client->request(Request::METHOD_POST, '/tracking/save', $this->saveParameters(['ticket' => 'FOREIGN-42']), [], ['HTTP_ACCEPT' => 'application/json']);
$this->assertStatusCode(400);
}
public function testTicketWithUnknownPrefixIsRejected(): void
{
$this->logInSession('unittest');
$this->client->request(Request::METHOD_POST, '/tracking/save', $this->saveParameters(['ticket' => 'WRONG-123']), [], ['HTTP_ACCEPT' => 'application/json']);
$this->assertStatusCode(400);
$data = json_decode((string) $this->client->getResponse()->getContent(), true);
self::assertIsArray($data);
self::assertArrayHasKey('message', $data);
// The 'unittest' user is German, so the message is localized (ADR i18n fix).
self::assertSame('Das angegebene Ticket hat kein gültiges Präfix.', $data['message']);
}
public function testTicketPrefixMustMatchExactlyNotMerelyStartWith(): void
{
$this->logInSession('unittest');
// 'SAX-1' starts with the configured prefix 'SA' as a string, but the
// Jira project key differs - must be rejected (regression guard for
// the str_starts_with() implementation).
$this->client->request(Request::METHOD_POST, '/tracking/save', $this->saveParameters(['ticket' => 'SAX-1']), [], ['HTTP_ACCEPT' => 'application/json']);
$this->assertStatusCode(400);
$data = json_decode((string) $this->client->getResponse()->getContent(), true);
self::assertIsArray($data);
self::assertArrayHasKey('message', $data);
// The 'unittest' user is German, so the message is localized (ADR i18n fix).
self::assertSame('Das angegebene Ticket hat kein gültiges Präfix.', $data['message']);
}
}