forked from fa/breadcrumb-the-shire
test(helpdesk): add OData injection rejection tests and meetings cache key coverage
Adds 11 tests for BcODataGateway covering getMeetingsForCustomer (empty, whitespace, not-configured), OData injection rejection for all customerNo methods (meetings, contract lines, escalation tickets, controlling), and valid input acceptance. Also adds meetingsKey format and inclusion tests for DebitorCacheControl. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -314,4 +314,102 @@ class BcODataGatewayTest extends TestCase
|
||||
$results = $gateway->getTicketsForControlling('10610');
|
||||
$this->assertSame([], $results);
|
||||
}
|
||||
|
||||
// ── Meetings: empty / whitespace / not-configured ──────────────
|
||||
|
||||
public function testGetMeetingsForCustomerReturnsEmptyForEmptyNo(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$results = $gateway->getMeetingsForCustomer('');
|
||||
$this->assertSame([], $results);
|
||||
}
|
||||
|
||||
public function testGetMeetingsForCustomerReturnsEmptyForWhitespace(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$results = $gateway->getMeetingsForCustomer(' ');
|
||||
$this->assertSame([], $results);
|
||||
}
|
||||
|
||||
public function testGetMeetingsForCustomerReturnsEmptyWhenNotConfigured(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings(false);
|
||||
$results = $gateway->getMeetingsForCustomer('10610');
|
||||
$this->assertSame([], $results);
|
||||
}
|
||||
|
||||
// ── OData injection rejection on customerNo methods ────────────
|
||||
|
||||
public function testGetMeetingsForCustomerRejectsODataInjection(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$gateway->getMeetingsForCustomer("10254' or '1'='1");
|
||||
}
|
||||
|
||||
public function testGetContractLinesForCustomerRejectsODataInjection(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$gateway->getContractLinesForCustomer("10254' or '1'='1");
|
||||
}
|
||||
|
||||
public function testGetEscalationTicketsForCustomerRejectsODataInjection(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$gateway->getEscalationTicketsForCustomer("10254' or '1'='1");
|
||||
}
|
||||
|
||||
public function testGetTicketsForControllingRejectsODataInjection(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$gateway->getTicketsForControlling("10254' or '1'='1");
|
||||
}
|
||||
|
||||
public function testGetMeetingsForCustomerRejectsParenthesesInjection(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$gateway->getMeetingsForCustomer("') or true or contains(Name,'");
|
||||
}
|
||||
|
||||
public function testGetContractLinesForCustomerRejectsParenthesesInjection(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$gateway->getContractLinesForCustomer("10254) or (1 eq 1");
|
||||
}
|
||||
|
||||
// ── Valid customerNo values still pass strict validation ───────
|
||||
|
||||
public function testGetMeetingsForCustomerAcceptsValidCustomerNo(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$threw = false;
|
||||
try {
|
||||
$gateway->getMeetingsForCustomer('10254');
|
||||
} catch (\InvalidArgumentException) {
|
||||
$this->fail('Valid customer number should pass strict input validation');
|
||||
} catch (\RuntimeException) {
|
||||
$threw = true;
|
||||
}
|
||||
// Either cURL failed (expected) or returned empty — both are fine
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function testGetContractLinesForCustomerAcceptsCustomerNoWithDash(): void
|
||||
{
|
||||
$gateway = $this->createGatewayWithSettings();
|
||||
$threw = false;
|
||||
try {
|
||||
$gateway->getContractLinesForCustomer('10254-A');
|
||||
} catch (\InvalidArgumentException) {
|
||||
$this->fail('Customer number with dash should pass strict input validation');
|
||||
} catch (\RuntimeException) {
|
||||
$threw = true;
|
||||
}
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,4 +71,16 @@ class DebitorCacheControlTest extends TestCase
|
||||
$keys = DebitorCacheControl::allDebitorCacheKeys('7', '10610');
|
||||
$this->assertContains('module.helpdesk.debitor.v2.controlling-tickets.7.10610', $keys);
|
||||
}
|
||||
|
||||
public function testMeetingsKeyFormat(): void
|
||||
{
|
||||
$key = DebitorCacheControl::meetingsKey('3', '10254');
|
||||
$this->assertSame('module.helpdesk.debitor.v2.meetings.3.10254', $key);
|
||||
}
|
||||
|
||||
public function testAllDebitorCacheKeysIncludesMeetingsKey(): void
|
||||
{
|
||||
$keys = DebitorCacheControl::allDebitorCacheKeys('3', '10254');
|
||||
$this->assertContains('module.helpdesk.debitor.v2.meetings.3.10254', $keys);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user