Skip to content

Commit

Permalink
feat(activity): change to use conversations API
Browse files Browse the repository at this point in the history
  • Loading branch information
jonniespratley authored and lalli-flores committed Mar 9, 2022
1 parent 9d2d65c commit dd31bfb
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 85 deletions.
59 changes: 46 additions & 13 deletions src/ActivitiesSDKAdapter.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {constructHydraId, deconstructHydraId} from '@webex/common';
import {ActivitiesAdapter} from '@webex/component-adapter-interfaces';
import {
from,
Expand All @@ -20,6 +21,31 @@ import logger from './logger';
* @see {@link https://github.com/webex/component-adapter-interfaces/blob/master/src/ActivitiesAdapter.js#L6}
*/

/**
* Extracts JSON card and files from server activity.
*
* @private
* @param {object} sdkActivity SDK activity object
* @returns {Array} Array of attachments.
*/
function parseSDKAttachments(sdkActivity) {
const {attachments = []} = sdkActivity;

try {
if (sdkActivity.object && sdkActivity.object.cards) {
sdkActivity.object.cards.forEach((c) => {
const card = JSON.parse(c);

attachments.push(card);
});
}
} catch (err) {
logger.warn('ACTIVITY', undefined, 'parseSDKAttachments()', `Unable parse attachments for activity with id "${sdkActivity.id}"`, err);
}

return attachments;
}

/**
* Maps SDK activity to adapter activity
*
Expand All @@ -29,12 +55,13 @@ import logger from './logger';
*/
function fromSDKActivity(sdkActivity) {
return {
ID: sdkActivity.id,
roomID: sdkActivity.roomId,
text: sdkActivity.text,
personID: sdkActivity.personId,
attachments: sdkActivity.attachments || [],
created: sdkActivity.created,
ID: sdkActivity.id ? constructHydraId('message', sdkActivity.id) : sdkActivity.ID,
roomID: sdkActivity.target ? constructHydraId('room', sdkActivity.target.id) : sdkActivity.roomID,
personID: sdkActivity.actor ? constructHydraId('person', sdkActivity.actor.id) : sdkActivity.personID,
text: sdkActivity.object ?
(sdkActivity.object.content || sdkActivity.object.displayName) : sdkActivity.text,
attachments: parseSDKAttachments(sdkActivity),
created: sdkActivity.published ? sdkActivity.published : sdkActivity.created,
};
}

Expand All @@ -61,10 +88,15 @@ export default class ActivitiesSDKAdapter extends ActivitiesAdapter {
*
* @private
*/
fetchActivity(activityID) {
async fetchActivity(activityID) {
logger.debug('ACTIVITY', activityID, 'fetchActivity()', ['called with', {activityID}]);

return this.datasource.messages.get(activityID);
const {id} = deconstructHydraId(activityID);
const service = 'conversation';
const resource = `activities/${id}`;
const {body} = await this.datasource.request({service, resource});

return body;
}

/**
Expand Down Expand Up @@ -140,11 +172,12 @@ export default class ActivitiesSDKAdapter extends ActivitiesAdapter {
* @returns {Observable.<Activity>} Observable that emits the posted activity (including id)
*/
postActivity(activity) {
const activity$ = from(this.datasource.messages.create({
roomId: activity.roomID,
text: activity.text,
attachments: activity.attachments,
})).pipe(
const activity$ = from(this.datasource.internal.conversation.post(
{
id: deconstructHydraId('room', activity.roomID).id,
},
activity.text,
)).pipe(
map(fromSDKActivity),
catchError((err) => {
logger.error('ACTIVITY', undefined, 'postActivity()', ['Unable to post activity', activity], err);
Expand Down
102 changes: 39 additions & 63 deletions src/ActivitiesSDKAdapter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,36 @@ import {isObservable} from 'rxjs';
import {last} from 'rxjs/operators';

import ActivitiesSDKAdapter from './ActivitiesSDKAdapter';
import createMockSDK, {mockSDKCardActivity} from './mockSdk';
import createMockSDK, {
mockSDKCardActivity, created, serverActivity, activityID, roomID, personID, ID, actorID, targetID,
} from './mockSdk';

describe('Activities SDK Adapter', () => {
let mockSDK;
let activitiesSDKAdapter;
let activityID;

const activityWithoutCard = {
ID: 'activityID1',
roomID: 'roomID1',
ID,
roomID,
text: 'text1',
personID: 'personID1',
created: '2021-02-02T14:38:16+00:00',
personID,
created,
};

beforeEach(() => {
mockSDK = createMockSDK();
activitiesSDKAdapter = new ActivitiesSDKAdapter(mockSDK);
activityID = 'activityID';
});

afterEach(() => {
mockSDK = null;
activitiesSDKAdapter = null;
activityID = null;
});

describe('getActivity()', () => {
beforeEach(() => {
activitiesSDKAdapter.fetchActivity = jest.fn(
() => Promise.resolve(mockSDKCardActivity),
() => Promise.resolve(serverActivity),
);
});

Expand All @@ -43,10 +43,10 @@ describe('Activities SDK Adapter', () => {
activitiesSDKAdapter.getActivity(activityID).subscribe(
(activity) => {
expect(activity).toMatchObject({
ID: 'activityID',
roomID: 'roomID',
ID,
roomID,
text: 'text',
personID: 'personID',
personID,
attachments: [
{
contentType: 'application/vnd.microsoft.card.adaptive',
Expand All @@ -71,7 +71,7 @@ describe('Activities SDK Adapter', () => {
},
},
],
created: '2022-02-02T14:38:16+00:00',
created,
});
done();
},
Expand All @@ -96,60 +96,34 @@ describe('Activities SDK Adapter', () => {
describe('postActivity()', () => {
test('emits the posted Activity object', (done) => {
const activityData = {
roomID: 'roomID',
roomID,
personID,
text: 'text',
card: {
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
type: 'AdaptiveCard',
version: '1.2',
body: [
{
type: 'TextBlock',
text: 'Adaptive Cards',
size: 'large',
},
],
actions: [
{
type: 'Action.OpenUrl',
url: 'http://adaptivecards.io',
title: 'Learn More',
},
],
},
};

activitiesSDKAdapter.datasource.internal.conversation.post = jest.fn(
() => Promise.resolve({
ID,
actor: {
id: actorID,
},
object: {
displayName: 'text',
},
target: {
id: targetID,
},
published: created,
}),
);

activitiesSDKAdapter.postActivity(activityData).pipe(last()).subscribe((activity) => {
expect(activity).toMatchObject({
ID: 'activityID',
roomID: 'roomID',
ID,
text: 'text',
personID: 'personID',
created: '2022-02-02T14:38:16+00:00',
attachments: [
{
contentType: 'application/vnd.microsoft.card.adaptive',
content: {
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
type: 'AdaptiveCard',
version: '1.2',
body: [
{
type: 'TextBlock',
text: 'Adaptive Cards',
size: 'large',
},
],
actions: [
{
type: 'Action.OpenUrl',
url: 'http://adaptivecards.io',
title: 'Learn More',
},
],
},
},
],
roomID,
personID,
created,
});
done();
});
Expand All @@ -158,7 +132,9 @@ describe('Activities SDK Adapter', () => {
test('emits the sdk error when messages.create returns a rejected promise', (done) => {
const sdkError = new Error('sdk-error');

activitiesSDKAdapter.datasource.messages.create = jest.fn(() => Promise.reject(sdkError));
activitiesSDKAdapter.datasource.internal.conversation.post = jest.fn(
() => Promise.reject(sdkError),
);

activitiesSDKAdapter.postActivity({}).subscribe(
() => {
Expand Down Expand Up @@ -190,7 +166,7 @@ describe('Activities SDK Adapter', () => {
roomID: 'roomID',
personID: 'personID',
type: 'submit',
created: '2022-02-03T14:26:16+00:00',
created,
});
done();
});
Expand Down
60 changes: 51 additions & 9 deletions src/mockSdk.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import {constructHydraId} from '@webex/common';
import mockDevices from './mockDevices';
import mockActivities from './mockActivities';

export const created = '2022-02-15T21:38:25.806Z';

// This is actor.id === personID
export const actorID = '1234';
export const personID = constructHydraId('person', actorID);

// This is target.id === roomID
export const targetID = '5678';
export const roomID = constructHydraId('room', targetID);

// This is activity.id === ID
export const activityID = '91011';
export const ID = constructHydraId('message', activityID);

export const mockSDKRoom = {
id: 'Y2lzY29zcGFyazovL3VzL1JPT00vYmMyMjY2YjAtZDZjMy0xMWViLWFlZjUtNmQ3NzkwOGJmY2Ji',
id: roomID,
type: 'group',
title: 'mock room',
};
Expand Down Expand Up @@ -30,7 +45,7 @@ export const mockSDKActivity = {
id: '789',
},
verb: 'post',
published: '2020-01-01T00:00:00.000Z',
published: created,
};

export const createMockSDKMediaStreams = () => {
Expand Down Expand Up @@ -157,7 +172,7 @@ export const mockSDKMembership = {
personDisplayName: 'Simon Damiano',
isModerator: false,
isMonitor: false,
created: '',
created,
};

export const mockSDKOrganization = {
Expand All @@ -170,11 +185,11 @@ const mockInternalConversationAPI = {
};

export const mockSDKCardActivity = {
id: 'activityID',
roomId: 'roomID',
id: ID,
roomId: roomID,
text: 'text',
personId: 'personID',
created: '2022-02-02T14:38:16+00:00',
personId: personID,
created,
attachments: [
{
contentType: 'application/vnd.microsoft.card.adaptive',
Expand Down Expand Up @@ -211,7 +226,34 @@ export const mockSDKAttachmentAction = {
firstName: 'My first name',
lastName: 'My last name',
},
created: '2022-02-03T14:26:16+00:00',
created,
};

export const activityWithCard = {
object: {
cards: [
'{"contentType":"application/vnd.microsoft.card.adaptive","content":{"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","type":"AdaptiveCard","version":"1.2","body":[{"type":"TextBlock","text":"Adaptive Cards","size":"large"}],"actions":[{"type":"Action.OpenUrl","url":"http://adaptivecards.io","title":"Learn More"}]}}',
],
},
};

export const serverActivity = {
id: activityID,
objectType: 'activity',
published: created,
actor: {
id: actorID,
},
object: {
objectType: 'comment',
content: 'text',
displayName: 'text',
cards: activityWithCard.object.cards,
},
target: {
id: targetID,
objectType: 'conversation',
},
};

/**
Expand Down Expand Up @@ -249,7 +291,7 @@ export default function createMockSDK(api = {}) {
},
meetings: {
create: jest.fn(() => Promise.resolve(mockSDKMeeting)),
getMeetingByType: jest.fn((_, ID) => (ID === 'meetingID' ? mockSDKMeeting : undefined)),
getMeetingByType: jest.fn((_, id) => (id === 'meetingID' ? mockSDKMeeting : undefined)),
members: {
on: jest.fn(),
},
Expand Down

0 comments on commit dd31bfb

Please sign in to comment.