mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-21 13:00:56 +01:00
Calendar Import: add unit tests to cover participants
Summary: Add unit tests to easily double-check matched participants in imported calendar events. This will simplify the addition of future features without the risk to break older workflows. Ref T15564 Closes T15905 Closes T15906 Test Plan: See green lights over your new unit tests: arc unit src/applications/calendar/import/__tests__/CalendarImportTestCase.php Reviewers: O1 Blessed Committers, aklapper Reviewed By: O1 Blessed Committers, aklapper Subscribers: aklapper, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15906, T15564, T15905 Differential Revision: https://we.phorge.it/D25767
This commit is contained in:
parent
d4d620fa6d
commit
3e53151815
4 changed files with 257 additions and 1 deletions
2
.arclint
2
.arclint
|
@ -65,7 +65,7 @@
|
|||
"text": {
|
||||
"type": "text",
|
||||
"exclude": [
|
||||
"(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json|expect))"
|
||||
"(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json|expect|ics))"
|
||||
]
|
||||
},
|
||||
"text-without-length": {
|
||||
|
|
|
@ -311,6 +311,7 @@ phutil_register_library_map(array(
|
|||
'BulkSelectParameterType' => 'applications/transactions/bulk/type/BulkSelectParameterType.php',
|
||||
'BulkStringParameterType' => 'applications/transactions/bulk/type/BulkStringParameterType.php',
|
||||
'BulkTokenizerParameterType' => 'applications/transactions/bulk/type/BulkTokenizerParameterType.php',
|
||||
'CalendarImportTestCase' => 'applications/calendar/import/__tests__/CalendarImportTestCase.php',
|
||||
'CalendarTimeUtil' => 'applications/calendar/util/CalendarTimeUtil.php',
|
||||
'CalendarTimeUtilTestCase' => 'applications/calendar/__tests__/CalendarTimeUtilTestCase.php',
|
||||
'CelerityAPI' => 'applications/celerity/CelerityAPI.php',
|
||||
|
@ -6318,6 +6319,7 @@ phutil_register_library_map(array(
|
|||
'BulkSelectParameterType' => 'BulkParameterType',
|
||||
'BulkStringParameterType' => 'BulkParameterType',
|
||||
'BulkTokenizerParameterType' => 'BulkParameterType',
|
||||
'CalendarImportTestCase' => 'PhabricatorTestCase',
|
||||
'CalendarTimeUtil' => 'Phobject',
|
||||
'CalendarTimeUtilTestCase' => 'PhabricatorTestCase',
|
||||
'CelerityAPI' => 'Phobject',
|
||||
|
|
|
@ -0,0 +1,231 @@
|
|||
<?php
|
||||
|
||||
final class CalendarImportTestCase extends PhabricatorTestCase {
|
||||
|
||||
protected function getPhabricatorTestCaseConfiguration() {
|
||||
return array(
|
||||
self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true,
|
||||
);
|
||||
}
|
||||
|
||||
// Indexes of the "expectedInviteesTests" test.
|
||||
const INVITED_USER = 0;
|
||||
const INVITED_EXPECTED = 1;
|
||||
const INVITED_RESULT = 2;
|
||||
|
||||
public function testIcsFileImportWithGuestThatIsHost() {
|
||||
$alice_unverified =
|
||||
$this->generateTestUserWithVerifiedMail(
|
||||
'alice@example.com',
|
||||
0);
|
||||
$lincoln_verified =
|
||||
$this->generateTestUserWithVerifiedMail(
|
||||
'a.lincoln@example.com',
|
||||
1);
|
||||
$alien_unverified =
|
||||
$this->generateTestUserWithVerifiedMail(
|
||||
'alien.unferified@example.com',
|
||||
0);
|
||||
$alien_verified =
|
||||
$this->generateTestUserWithVerifiedMail(
|
||||
'alien.verified@example.com',
|
||||
1);
|
||||
|
||||
// Tests are event-based. Each event has their expected invitees.
|
||||
$tests = array(
|
||||
// Test zero. Alice imports an event with A.Lincoln.
|
||||
array(
|
||||
'test' => pht('alice invites a.lincoln via verified email'),
|
||||
'file' => 'simple-event-alincoln-guest.ics',
|
||||
'fileAuthor' => $alice_unverified,
|
||||
'expectedInvitees' => 3,
|
||||
'expectedInviteesTests' => array(
|
||||
// Documentation:
|
||||
// Array 0 (INVITED_USER): User object
|
||||
// Array 1 (INVITED_EXPECTED): Presence (bool)
|
||||
array($lincoln_verified, false),
|
||||
array($alice_unverified, false),
|
||||
array($alien_unverified, false),
|
||||
array($alien_verified, false),
|
||||
),
|
||||
),
|
||||
// Test one. A.Lincoln imports an event with A.Lincoln.
|
||||
array(
|
||||
'test' => pht('a.lincoln self-invite via verified email'),
|
||||
'file' => 'simple-event-alincoln-guest.ics',
|
||||
'fileAuthor' => $lincoln_verified,
|
||||
'expectedInvitees' => 3,
|
||||
'expectedInviteesTests' => array(
|
||||
// array($lincoln_verified, true), // Self-invitation. T15564
|
||||
array($alice_unverified, false),
|
||||
array($alien_unverified, false),
|
||||
array($alien_verified, false),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($tests as $test) {
|
||||
$this->runIcsFileImportTestWithExpectedResults(
|
||||
$test['test'],
|
||||
$test['file'],
|
||||
$test['fileAuthor'],
|
||||
$test['expectedInvitees'],
|
||||
$test['expectedInviteesTests']);
|
||||
}
|
||||
}
|
||||
|
||||
private function runIcsFileImportTestWithExpectedResults(
|
||||
$test, $file, $importer_author, $expecteds, $invitees_tests) {
|
||||
|
||||
$ics_path = __DIR__.'/events/'.$file;
|
||||
|
||||
// Prepare a calendar import.
|
||||
$import_type = new PhabricatorCalendarICSFileImportEngine();
|
||||
$calendar_import = PhabricatorCalendarImport::initializeNewCalendarImport(
|
||||
$importer_author,
|
||||
clone $import_type);
|
||||
|
||||
// Create the File containing the ICS example.
|
||||
$file_data = Filesystem::readFile($ics_path);
|
||||
$file_test_engine = new PhabricatorTestStorageEngine();
|
||||
$file_params = array(
|
||||
'name' => $file,
|
||||
'viewPolicy' => PhabricatorPolicies::POLICY_USER,
|
||||
'authorPHID' => $importer_author->getPHID(),
|
||||
'storageEngines' => array($file_test_engine),
|
||||
);
|
||||
$file_up = PhabricatorFile::newFromFileData($file_data, $file_params);
|
||||
|
||||
// Create a calendar import with our ICS file.
|
||||
$import_xactions = array();
|
||||
$import_xactions[] = id(new PhabricatorCalendarImportTransaction())
|
||||
->setTransactionType(
|
||||
PhabricatorCalendarImportICSFileTransaction::TRANSACTIONTYPE)
|
||||
->setNewValue($file_up->getPHID());
|
||||
|
||||
// Persist the calendar import and get it.
|
||||
id(new PhabricatorCalendarImportEditor())
|
||||
->setActor($importer_author)
|
||||
->setContentSource($this->newContentSource())
|
||||
->applyTransactions($calendar_import, $import_xactions);
|
||||
|
||||
$import_type->importEventsFromSource(
|
||||
$importer_author,
|
||||
$calendar_import,
|
||||
false);
|
||||
|
||||
// Find imported events from the perspective of the importer author itself.
|
||||
// So we check if we gained some extra people email visibility by mistake.
|
||||
// The backend does not support attachInvitees() and it's done by default.
|
||||
$events = (new PhabricatorCalendarEventQuery())
|
||||
->setViewer($importer_author)
|
||||
->withImportSourcePHIDs(array($calendar_import->getPHID()))
|
||||
->execute();
|
||||
|
||||
// At the moment test cases are hardcoded with one event.
|
||||
$this->assertEqual(
|
||||
1,
|
||||
count($events),
|
||||
pht('Unexpected events in file "%s" on test "%s"',
|
||||
$file,
|
||||
$test));
|
||||
|
||||
// Take the first event.
|
||||
$event = head($events);
|
||||
|
||||
// How many people we invited in this event.
|
||||
$this->assertEqual(
|
||||
$expecteds,
|
||||
count($event->getInvitees()),
|
||||
pht('Unexpected invitees in file "%s" on test "%s"', $file, $test));
|
||||
|
||||
foreach ($invitees_tests as $invitees_test) {
|
||||
$this->assertMatchingInvitees($test, $file, $event, $invitees_tests);
|
||||
}
|
||||
|
||||
$event->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the invitees matches.
|
||||
*/
|
||||
private function assertMatchingInvitees($test, $file, $event, $expecteds) {
|
||||
|
||||
// Index what we expect, by user PHID.
|
||||
$expected_users_by_phid = [];
|
||||
foreach ($expecteds as $expected_invited_data) {
|
||||
$user_phid = $expected_invited_data[self::INVITED_USER]
|
||||
->getPHID();
|
||||
$expected_users_by_phid[$user_phid]
|
||||
= $expected_invited_data;
|
||||
}
|
||||
|
||||
// Get current invitees (mixed between "PHID-CXNV" and "PHID-USER").
|
||||
$actuals_phids_mixed = mpull($event->getInvitees(), 'getInviteePHID');
|
||||
|
||||
// Get just actual users.
|
||||
$actual_users = (new PhabricatorUser())->loadAllWhere(
|
||||
'phid IN (%Ls)',
|
||||
$actuals_phids_mixed);
|
||||
$actual_users = mpull($actual_users, null, 'getPHID');
|
||||
|
||||
// Map actual users with the expected ones.
|
||||
foreach ($actual_users as $actual_user) {
|
||||
$user_phid = $actual_user->getPHID();
|
||||
$found = isset($expected_users_by_phid[$user_phid]);
|
||||
if (!$found) {
|
||||
$expected_users_by_phid[$user_phid] = array();
|
||||
}
|
||||
$expected_users_by_phid[$user_phid][self::INVITED_RESULT]
|
||||
= $found;
|
||||
}
|
||||
|
||||
// In the future it may be useful to also check external users
|
||||
// by their email. In case, start from here!
|
||||
// but note that the 'getURI()' returns 'mailto:' stuff.
|
||||
// $actual_externals = (new PhabricatorCalendarExternalInvitee())
|
||||
// ->loadAllWhere(
|
||||
// 'phid IN (%Ls)',
|
||||
// $actuals_phids_mixed);
|
||||
// $actual_externals = mpull($actual_externals, null, 'getURI');
|
||||
|
||||
// Check results (matched or not).
|
||||
foreach ($expected_users_by_phid as $phid => $expecteds_data) {
|
||||
$expected = idx($expecteds_data, self::INVITED_EXPECTED, null);
|
||||
$result = idx($expecteds_data, self::INVITED_RESULT, false);
|
||||
$user = idx($expecteds_data, self::INVITED_USER, null);
|
||||
if ($expected !== null) {
|
||||
$this->assertEqual(
|
||||
$expected,
|
||||
$result,
|
||||
pht('Unexpected presence of user "%s" in file "%s" on test "%s"',
|
||||
$user == null ? '(unknown)' : $user->loadPrimaryEmailAddress(),
|
||||
$file,
|
||||
$test));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a test user with a specific verified (or not) email.
|
||||
* @param string $mail Email address
|
||||
* @param int $is_verified 0: unverified, 1: verified
|
||||
* @return PhabricatorUser
|
||||
*/
|
||||
private function generateTestUserWithVerifiedMail($mail, $is_verified) {
|
||||
$user = $this->generateNewTestUser();
|
||||
|
||||
// Set our primary address as verified or not.
|
||||
$email = id(new PhabricatorUserEmail())->loadOneWhere(
|
||||
'userPHID = %s',
|
||||
$user->getPHID());
|
||||
|
||||
$email->setAddress($mail);
|
||||
$email->setIsVerified($is_verified);
|
||||
$email->setIsPrimary(true);
|
||||
$email->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:-//Phacility//Phabricator//EN
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20240205
|
||||
DTEND;VALUE=DATE:20240206
|
||||
DTSTAMP:20240411T230207Z
|
||||
ORGANIZER;CN=asd@group.calendar.google.com:mailto:lol@group.calendar.google.com
|
||||
UID:blabla@google.com
|
||||
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=
|
||||
foo@example.com;X-NUM-GUESTS=0:mailto:foo@example.com
|
||||
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=a.
|
||||
lincoln@example.com;X-NUM-GUESTS=0:mailto:a.lincoln@example.com
|
||||
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CN=
|
||||
alien@example.com;X-NUM-GUESTS=0:mailto:alien@example.com
|
||||
CREATED:20240123T154250Z
|
||||
LAST-MODIFIED:20240123T162620Z
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:A Lincoln, Foo and Alien to FOSDEM 2024
|
||||
TRANSP:TRANSPARENT
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
Loading…
Reference in a new issue