*/
private array $tempFiles = [];
public function testHandleValidFile(): void
{
$xml = <<<'XML'
-
god@foundation.edu
Hari
Seldon
-
picard@federation.earth
Jean-Luc
Picard
-
jackwithapostrophe@sgc.mil
Jack
O'Neill
XML;
$createContactCommand = $this->createCreateContactCommandMock(
1,
['god@foundation.edu', 'picard@federation.earth', 'jackwithapostrophe@sgc.mil'],
new BatchResult(0, 0, 3),
);
$processImportState = $this->createMock(ProcessImportState::class);
$processImportState->expects($this->exactly(1))->method('start');
$processImportState->expects($this->exactly(1))->method('finish');
$processImportState->expects($this->exactly(1))->method('contactFail')->with(0);
$processImportState->expects($this->exactly(1))->method('contactDuplicate')->with(0);
$processImportState->expects($this->exactly(1))->method('contactSuccess')->with(3);
$processImportState->method('uuid')->willReturn(Uuid::uuid7());
$job = new ProcessImport(
$this->createTempFile($xml),
$processImportState,
);
$job->handle($createContactCommand);
}
public function testHandleMultipleTextNodes(): void
{
$xml = <<<'XML'
-
god@on.edu
Hari
Seldon
XML;
$createContactCommand = $this->createCreateContactCommandMock(
1,
['god@foundation.edu'],
new BatchResult(0, 0, 1),
);
$processImportState = $this->createMock(ProcessImportState::class);
$processImportState->expects($this->exactly(1))->method('start');
$processImportState->expects($this->exactly(1))->method('finish');
$processImportState->expects($this->exactly(1))->method('contactFail')->with(0);
$processImportState->expects($this->exactly(1))->method('contactDuplicate')->with(0);
$processImportState->expects($this->exactly(1))->method('contactSuccess')->with(1);
$processImportState->method('uuid')->willReturn(Uuid::uuid7());
$job = new ProcessImport(
$this->createTempFile($xml),
$processImportState,
);
$job->handle($createContactCommand);
}
public function testHandleValidMultipleBatches(): void
{
$xml = '';
$emails = [];
for ($i = 0; $i <= 5001; $i++) {
$xml .= '-
god' . $i . '@foundation.edu
Hari
Seldon
';
$emails[] = 'god@foundation.edu' . $i;
}
$xml .= '';
$createContactCommand = $this->createCreateContactCommandMock(
2,
[],
[
new BatchResult(0, 0, 5000),
new BatchResult(0, 0, 1),
],
);
$processImportState = $this->createMock(ProcessImportState::class);
$processImportState->expects($this->exactly(1))->method('start');
$processImportState->expects($this->exactly(1))->method('finish');
$processImportState->expects($this->exactly(2))->method('contactFail')->with(0);
$processImportState->expects($this->exactly(2))
->method('contactDuplicate')
->with($this->callback(static fn (int $duplicates): bool => $duplicates === 0 || $duplicates === 1));
$processImportState->expects($this->exactly(2))
->method('contactSuccess')
->with($this->callback(static fn (int $processed): bool => $processed === 5000 || $processed === 1));
$processImportState->method('uuid')->willReturn(Uuid::uuid7());
$job = new ProcessImport(
$this->createTempFile($xml),
$processImportState,
);
$job->handle($createContactCommand);
}
public function testHandleInvalidFile(): void
{
$xml = <<<'XML'
-
Hari
Seldon
XML;
$processImportState = $this->createMock(ProcessImportState::class);
$processImportState->expects($this->exactly(1))->method('start');
$processImportState->expects($this->exactly(1))->method('finish');
$failCallsWithOne = 0;
$processImportState->expects($this->atLeastOnce())
->method('contactFail')
->willReturnCallback(function (int $count) use (&$failCallsWithOne): void {
if ($count === 1) {
$failCallsWithOne++;
}
});
$processImportState->expects($this->exactly(1))->method('contactDuplicate')->with(0);
$processImportState->expects($this->exactly(1))->method('contactSuccess')->with(0);
$processImportState->method('uuid')->willReturn(Uuid::uuid7());
$job = new ProcessImport(
$this->createTempFile($xml),
$processImportState,
);
$job->handle($this->createCreateContactCommandMock());
$this->assertGreaterThan(0, $failCallsWithOne);
}
public function testHandleInvalidStructure(): void
{
$xml = <<<'XML'
-
god@foundation.edu
Hari
Seldon
anubis@badguy.space
No-imported
Anubis
XML;
$createContactCommand = $this->createCreateContactCommandMock(
1,
['god@foundation.edu'],
new BatchResult(0, 0, 1),
);
$processImportState = $this->createMock(ProcessImportState::class);
$processImportState->expects($this->exactly(1))->method('start');
$processImportState->expects($this->exactly(1))->method('finish');
$processImportState->expects($this->exactly(1))->method('contactFail')->with(0);
$processImportState->expects($this->exactly(1))->method('contactDuplicate')->with(0);
$processImportState->expects($this->exactly(1))->method('contactSuccess')->with(1);
$job = new ProcessImport(
$this->createTempFile($xml),
$processImportState,
);
$job->handle($createContactCommand);
}
public function testHandleReallyBadXml(): void
{
$xml = 'NOT XML';
$createContactCommand = $this->createCreateContactCommandMock(
1,
[],
new BatchResult(0, 0, 0),
);
$processImportState = $this->createMock(ProcessImportState::class);
$processImportState->expects($this->exactly(1))->method('start');
$processImportState->expects($this->exactly(1))->method('finish');
$processImportState->expects($this->exactly(1))->method('contactFail')->with(0);
$processImportState->expects($this->exactly(1))->method('contactDuplicate')->with(0);
$processImportState->expects($this->exactly(1))->method('contactSuccess')->with(0);
$job = new ProcessImport(
$this->createTempFile($xml),
$processImportState,
);
$job->handle($createContactCommand);
}
protected function tearDown(): void
{
Storage::disk('local')->delete($this->tempFiles);
$this->tempFiles = [];
parent::tearDown();
}
private function createTempFile(string $contents): string
{
$path = 'process-import/' . Uuid::uuid7()->toString() . '.xml';
Storage::disk('local')->put($path, $contents);
$this->tempFiles[] = $path;
return $path;
}
private function createCreateContactCommandMock(
?int $expectedCalls = null,
array $emails = [],
BatchResult|array|null $batchResult = null,
): CreateContactCommand {
$createContactCommand = $this->createMock(CreateContactCommand::class);
$expectation = $expectedCalls !== null
? $createContactCommand->expects($this->exactly($expectedCalls))->method('multipleExecute')
: $createContactCommand->method('multipleExecute');
if ($expectedCalls !== null) {
$expectation
->with($this->callback(function (array $intents) use ($emails): bool {
if ($emails === []) {
return true;
}
$argEmails = array_map(
static fn (CreateContactIntent $intent): string => $intent->email,
$intents,
);
sort($argEmails);
sort($emails);
return $argEmails === $emails;
}));
}
if (is_array($batchResult)) {
$expectation->willReturnOnConsecutiveCalls(...$batchResult);
} elseif ($batchResult instanceof BatchResult) {
$expectation->willReturn($batchResult);
} else {
$expectation->willReturn(new BatchResult(0, 0, 0));
}
return $createContactCommand;
}
}