diff --git a/packages/v1-ready/zoom/jest-setup.js b/packages/v1-ready/zoom/jest-setup.js index 9dd3e0d..ec2bfca 100644 --- a/packages/v1-ready/zoom/jest-setup.js +++ b/packages/v1-ready/zoom/jest-setup.js @@ -1,2 +1,9 @@ -const {globalSetup} = require('@friggframework/test'); -module.exports = globalSetup; +const { globalSetup } = require('@friggframework/test'); + +module.exports = () => { + globalSetup(); + + process.env.ZOOM_CLIENT_ID = 'ZOOM_CLIENT_ID'; + process.env.ZOOM_CLIENT_SECRET = 'ZOOM_CLIENT_SECRET'; + process.env.REDIRECT_URI = 'http://localhost:3000'; +}; diff --git a/packages/v1-ready/zoom/jest-teardown.js b/packages/v1-ready/zoom/jest-teardown.js index 5bc7251..d0c6426 100644 --- a/packages/v1-ready/zoom/jest-teardown.js +++ b/packages/v1-ready/zoom/jest-teardown.js @@ -1,2 +1,2 @@ -const {globalTeardown} = require('@friggframework/test'); +const { globalTeardown } = require('@friggframework/test'); module.exports = globalTeardown; diff --git a/packages/v1-ready/zoom/tests/api.test.js b/packages/v1-ready/zoom/tests/api.test.js new file mode 100644 index 0000000..b8ecefc --- /dev/null +++ b/packages/v1-ready/zoom/tests/api.test.js @@ -0,0 +1,121 @@ +const { Api } = require('../api'); +const config = require('../defaultConfig.json'); +const { randomBytes } = require('crypto'); + +const apiParams = { + client_id: process.env.ZOOM_CLIENT_ID, + client_secret: process.env.ZOOM_CLIENT_SECRET, + redirect_uri: process.env.REDIRECT_URI, +}; +const api = new Api(apiParams); + +const getRandomId = () => randomBytes(10).toString('hex'); + +describe(`${config.label} API tests`, () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + // Constructor + describe('Constructor', () => { + it('Should initialize with expected properties', () => { + expect(api.client_id).toBe(process.env.ZOOM_CLIENT_ID); + expect(api.client_secret).toBe(process.env.ZOOM_CLIENT_SECRET); + expect(api.redirect_uri).toBe(process.env.REDIRECT_URI); + expect(api.baseUrl).toBe('https://api.zoom.us/v2'); + }); + }); + + // User List + describe('Get user list', () => { + it('Should call _get with the proper URL', async () => { + const mockResponse = getRandomId(); + api._get = jest.fn().mockResolvedValue(mockResponse); + const response = await api.getUserList(); + expect(api._get).toHaveBeenCalledWith({ + url: api.baseUrl + '/users?status=active', + }); + expect(response).toEqual(mockResponse); + }); + }); + + // Meeting List by User + describe('Get meeting list by user', () => { + it('Should call _get with the proper URL', async () => { + const mockResponse = getRandomId(); + api._get = jest.fn().mockResolvedValue(mockResponse); + const userId = getRandomId(); + const response = await api.getMeetingListByUser(userId); + expect(api._get).toHaveBeenCalledWith({ + url: api.baseUrl + `/users/${userId}/meetings`, + }); + expect(response).toEqual(mockResponse); + }); + }); + + // Meeting Details + describe('Get meeting details', () => { + it('Should call _get with the proper URL', async () => { + const mockResponse = getRandomId(); + api._get = jest.fn().mockResolvedValue(mockResponse); + const meetingId = getRandomId(); + const response = await api.getMeetingDetails(meetingId); + expect(api._get).toHaveBeenCalledWith({ + url: api.baseUrl + `/meetings/${meetingId}`, + }); + expect(response).toEqual(mockResponse); + }); + }); + + // Change Meeting Topic + describe('Change meeting topic', () => { + it('Should call _authedPatch with the proper URL and body', async () => { + const mockResponse = getRandomId(); + api._authedPatch = jest.fn().mockResolvedValue(mockResponse); + const meetingId = getRandomId(); + const topic = 'Updated Topic'; + const response = await api.changeMeetingTopic(meetingId, topic); + expect(api._authedPatch).toHaveBeenCalledWith( + `/meetings/${meetingId}`, + { topic } + ); + expect(response).toEqual(mockResponse); + }); + }); + + // Create New Meeting + describe('Create new meeting', () => { + it('Should call _authedPost with the proper URL and body', async () => { + const mockResponse = getRandomId(); + api._authedPost = jest.fn().mockResolvedValue(mockResponse); + const userId = getRandomId(); + const topic = 'New Meeting'; + const response = await api.createNewMeeting(userId, topic); + expect(api._authedPost).toHaveBeenCalledWith( + `/users/${userId}/meetings`, + { + topic: topic, + type: 2, + start_time: expect.any(String), + duration: 1440, + timezone: 'America/New_York', + } + ); + expect(response).toEqual(mockResponse); + }); + }); + + // Delete Meeting + describe('Delete meeting', () => { + it('Should call _authedDelete with the proper URL', async () => { + const mockResponse = getRandomId(); + api._authedDelete = jest.fn().mockResolvedValue(mockResponse); + const meetingId = getRandomId(); + const response = await api.deleteMeeting(meetingId); + expect(api._authedDelete).toHaveBeenCalledWith( + `/meetings/${meetingId}` + ); + expect(response).toEqual(mockResponse); + }); + }); +}); diff --git a/packages/v1-ready/zoom/tests/auther.test.js b/packages/v1-ready/zoom/tests/auther.test.js new file mode 100644 index 0000000..45b6d28 --- /dev/null +++ b/packages/v1-ready/zoom/tests/auther.test.js @@ -0,0 +1,143 @@ +const { + connectToDatabase, + disconnectFromDatabase, + createObjectId, + Auther, +} = require('@friggframework/core'); +const { testAutherDefinition } = require('@friggframework/devtools'); +const { Authenticator } = require('@friggframework/test'); +const { Definition } = require('../definition'); + +const mocks = { + getUserDetails: { + id: '', + first_name: 'Jane', + last_name: 'Doe', + display_name: 'Jane Doe', + email: 'jane.doe@lefthook.com', + type: 1, + role_name: 'Owner', + pmi: 0, + use_pmi: false, + personal_meeting_url: 'https://us04web.zoom.us/j/redacted?pwd=redacted', + timezone: '', + verified: 0, + dept: '', + created_at: '2023-07-26T14:16:21Z', + last_login_time: '2024-06-26T15:58:30Z', + last_client_version: '5.17.11.34827(win)', + pic_url: 'https://us04web.zoom.us/p/v2/', + cms_user_id: '', + jid: 'test@xmpp.zoom.us', + group_ids: [], + im_group_ids: [], + account_id: '', + language: 'en-US', + phone_country: '', + phone_number: '', + status: 'active', + job_title: '', + location: '', + login_types: [1], + role_id: '0', + cluster: 'us04', + user_created_at: '2023-07-26T14:16:21Z', + }, + tokenResponse: { + access_token: 'redacted', + token_type: 'bearer', + refresh_token: 'redacted', + expires_in: 3599, + scope: 'user:read:user user:read:email meeting:read:list_meetings meeting:write:meeting meeting:update:meeting', + }, + authorizeResponse: { + base: '/redirect/zoom', + data: { + code: 'test-code', + state: 'null', + }, + }, +}; + +testAutherDefinition(Definition, mocks); + +describe.skip('Zoom Module Live Tests', () => { + let module, authUrl; + beforeAll(async () => { + await connectToDatabase(); + module = await Auther.getInstance({ + definition: Definition, + userId: createObjectId(), + }); + }); + + afterAll(async () => { + await module.CredentialModel.deleteMany(); + await module.EntityModel.deleteMany(); + await disconnectFromDatabase(); + }); + + describe('getAuthorizationRequirements() test', () => { + it('should return auth requirements', async () => { + const requirements = await module.getAuthorizationRequirements(); + expect(requirements).toBeDefined(); + expect(requirements.type).toEqual('oauth2'); + expect(requirements.url).toBeDefined(); + authUrl = requirements.url; + }); + }); + + describe('Authorization requests', () => { + let firstRes; + it('processAuthorizationCallback()', async () => { + const response = await Authenticator.oauth2(authUrl); + firstRes = await module.processAuthorizationCallback({ + data: { + code: response.data.code, + }, + }); + expect(firstRes).toBeDefined(); + expect(firstRes.entity_id).toBeDefined(); + expect(firstRes.credential_id).toBeDefined(); + }); + it('retrieves existing entity on subsequent calls', async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)); + const response = await Authenticator.oauth2(authUrl); + const res = await module.processAuthorizationCallback({ + data: { + code: response.data.code, + }, + }); + expect(res).toEqual(firstRes); + }); + it('refresh the token', async () => { + module.api.access_token = 'foobar'; + const res = await module.testAuth(); + expect(res).toBeTruthy(); + }); + }); + describe('Test credential retrieval and module instantiation', () => { + it('retrieve by entity id', async () => { + const newModule = await Auther.getInstance({ + userId: module.userId, + entityId: module.entity.id, + definition: Definition, + }); + expect(newModule).toBeDefined(); + expect(newModule.entity).toBeDefined(); + expect(newModule.credential).toBeDefined(); + expect(await newModule.testAuth()).toBeTruthy(); + }); + + it('retrieve by credential id', async () => { + const newModule = await Auther.getInstance({ + userId: module.userId, + credentialId: module.credential.id, + definition: Definition, + }); + expect(newModule).toBeDefined(); + expect(newModule.credential).toBeDefined(); + expect(await newModule.testAuth()).toBeTruthy(); + }); + }); +});