diff --git a/spec/controllers/events_spec.cr b/spec/controllers/events_spec.cr index 2e7b9dfd..e23ceac6 100644 --- a/spec/controllers/events_spec.cr +++ b/spec/controllers/events_spec.cr @@ -185,6 +185,34 @@ describe Events, tags: ["event"] do guests.compact_map(&.photo).should eq(["http://example.com/first.jpg"]) guests.compact_map(&.extension_data).should eq([{"fizz" => "buzz"}, {} of String => String?]) end + + # PPT-2294: External attendee name should be preserved from input, not replaced with email from calendar API + it "returns external attendee name from guest record when calendar API returns email as name" do + # Use fixture where calendar API returns email as name for external attendees + WebMock.stub(:post, "https://graph.microsoft.com/v1.0/users/dev%40acaprojects.onmicrosoft.com/calendar/events") + .to_return(body: File.read("./spec/fixtures/events/o365/create_external_attendee_email_as_name.json")) + WebMock.stub(:get, "https://graph.microsoft.com/v1.0/users/dev@acaprojects.com/calendar/events/AAMkADE3YmQxMGQ2LTRmZDgtNDljYy1hNDg1LWM0NzFmMGI0ZTQ3YgBGAAAAAADFYQb3DJ_xSJHh14kbXHWhBwB08dwEuoS_QYSBDzuv558sAAAAAAENAAB08dwEuoS_QYSBDzuv558sAACGVOwUAAA=") + .to_return(body: File.read("./spec/fixtures/events/o365/create_external_attendee_email_as_name.json")) + WebMock.stub(:patch, "https://graph.microsoft.com/v1.0/users/dev%40acaprojects.onmicrosoft.com/calendar/events/") + .to_return(body: File.read("./spec/fixtures/events/o365/update.json")) + WebMock.stub(:get, "https://graph.microsoft.com/v1.0/users/dev%40acaprojects.com/calendars") + .to_return(body: File.read("./spec/fixtures/calendars/o365/show.json")) + + req_body = EventsHelper.create_event_input + + tenant = get_tenant + EventMetadatasHelper.create_event(tenant.id) + response = client.post(EVENTS_BASE, headers: headers, body: req_body) + created_event = JSON.parse(response.body) + + # Find the external attendee (jon@example.com) in the response + attendees = created_event["attendees"].as_a + external_attendee = attendees.find { |a| a["email"].as_s == "jon@example.com" } + + # The name should be "John" (from input/guest record), not "jon@example.com" (from calendar API) + external_attendee.should_not be_nil + external_attendee.not_nil!["name"].as_s.should eq("John") + end end describe "#update" do diff --git a/spec/fixtures/events/o365/create_external_attendee_email_as_name.json b/spec/fixtures/events/o365/create_external_attendee_email_as_name.json new file mode 100644 index 00000000..4ead7719 --- /dev/null +++ b/spec/fixtures/events/o365/create_external_attendee_email_as_name.json @@ -0,0 +1,120 @@ +{ + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('dev%40acaprojects.onmicrosoft.com')/calendar/events/$entity", + "@odata.etag": "W/\"dPHcBLqEvkGEgQ87r+efLAAAhk36bA==\"", + "id": "AAMkADE3YmQxMGQ2LTRmZDgtNDljYy1hNDg1LWM0NzFmMGI0ZTQ3YgBGAAAAAADFYQb3DJ_xSJHh14kbXHWhBwB08dwEuoS_QYSBDzuv558sAAAAAAENAAB08dwEuoS_QYSBDzuv558sAACGVOwUAAA=", + "createdDateTime": "2020-09-13T22:44:39.7263717Z", + "lastModifiedDateTime": "2020-09-13T22:44:40.4089746Z", + "changeKey": "dPHcBLqEvkGEgQ87r+efLAAAhk36bA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "Australia/Sydney", + "originalEndTimeZone": "Australia/Sydney", + "iCalUId": "040000008200E00074C5B7101A82E008000000006DE2E3761F8AD6010000000000000000100000009CCCDBB1F09DE74D8B157797D97F6A10", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "tentative event response status and default timezone trial updated", + "bodyPreview": "yeehaw hiya", + "importance": "normal", + "sensitivity": "private", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": true, + "responseRequested": true, + "seriesMasterId": null, + "showAs": "busy", + "type": "singleInstance", + "webLink": "https://outlook.office365.com/owa/?itemid=AAMkADE3YmQxMGQ2LTRmZDgtNDljYy1hNDg1LWM0NzFmMGI0ZTQ3YgBGAAAAAADFYQb3DJ%2BxSJHh14kbXHWhBwB08dwEuoS%2BQYSBDzuv558sAAAAAAENAAB08dwEuoS%2BQYSBDzuv558sAACGVOwUAAA%3D&exvsurl=1&path=/calendar/item", + "onlineMeetingUrl": null, + "isOnlineMeeting": false, + "onlineMeetingProvider": "unknown", + "allowNewTimeProposals": true, + "recurrence": { + "pattern": { + "type": "daily", + "interval": 2 + }, + "range": { + "type": "daily", + "startDate": "2020-08-27T14:45:00.0000000", + "endDate": "2020-11-27T15:46:00.0000000" + } + }, + "onlineMeeting": null, + "responseStatus": { + "response": "organizer", + "time": "0001-01-01T00:00:00Z" + }, + "body": { + "contentType": "text", + "content": "yeehaw hiya" + }, + "start": { + "dateTime": "2020-08-27T14:45:00.0000000", + "timeZone": "Australia/Sydney" + }, + "end": { + "dateTime": "2020-08-27T15:46:00.0000000", + "timeZone": "Australia/Sydney" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "attendees": [ + { + "type": "required", + "status": { + "response": "accepted", + "time": "2020-09-13T22:44:39Z" + }, + "emailAddress": { + "name": "amit@redant.com.au", + "address": "amit@redant.com.au" + } + }, + { + "type": "required", + "status": { + "response": "tentativelyAccepted", + "time": "2020-09-13T22:44:39Z" + }, + "emailAddress": { + "name": "jon@example.com", + "address": "jon@example.com" + } + }, + { + "type": "required", + "status": { + "response": "none", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "RM-AU-DP-L105-Swiss-Alps", + "address": "RMAUDPSwissAlps@booking.demo.acaengine.com" + } + }, + { + "type": "required", + "status": { + "response": "accepted", + "time": "2020-09-13T22:44:39Z" + }, + "emailAddress": { + "name": "Developer", + "address": "dev@acaprojects.onmicrosoft.com" + } + } + ], + "organizer": { + "emailAddress": { + "name": "Developer", + "address": "dev@acaprojects.onmicrosoft.com" + } + } +} diff --git a/src/models/event.cr b/src/models/event.cr index 5a49141d..0240856e 100644 --- a/src/models/event.cr +++ b/src/models/event.cr @@ -25,7 +25,12 @@ class StaffApi::Event if visitor = visitors[attendee.email]? attendee.checked_in = is_parent_metadata ? false : visitor.checked_in attendee.visit_expected = visitor.visit_expected - attendee.extension_data = visitor.try(&.guest).try(&.extension_data) || JSON.parse("{}") + if guest = visitor.try(&.guest) + attendee.extension_data = guest.extension_data || JSON.parse("{}") + if name = guest.name.presence + attendee.name = name + end + end end attendee diff --git a/test b/test index f67e0059..1c7afcf8 100755 --- a/test +++ b/test @@ -19,7 +19,12 @@ docker compose build -q exit_code="0" -docker compose run --rm test $@ || exit_code="$?" +tty_flag="" +if [ ! -t 0 ]; then + tty_flag="-T" +fi + +docker compose run --rm $tty_flag test "$@" || exit_code="$?" docker compose down &> /dev/null