const test = require('tape') ; const ADMIN_TOKEN = '38700987-c7a4-4685-a5bb-af378f9734de'; const authAdmin = {bearer: ADMIN_TOKEN}; const { createClient } = require('./http-client'); const request = createClient({ baseUrl: 'http://127.0.0.1:3000/v1' }); const {createVoipCarrier, createServiceProvider, createPhoneNumber, createAccount, deleteObjectBySid } = require('./utils'); process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); }); test('application tests', async(t) => { const app = require('../app'); let sid; try { let result; /* add service provider, phone number, and voip carrier */ const voip_carrier_sid = await createVoipCarrier(request); const service_provider_sid = await createServiceProvider(request); const phone_number_sid = await createPhoneNumber(request, voip_carrier_sid); const account_sid = await createAccount(request, service_provider_sid); /* add an invalid application app_json */ result = await request.post('/Applications', { resolveWithFullResponse: true, simple: false, auth: authAdmin, json: true, body: { name: 'daveh', account_sid, call_hook: { url: 'http://example.com' }, call_status_hook: { url: 'http://example.com/status', method: 'POST' }, messaging_hook: { url: 'http://example.com/sms' }, app_json : '[\ {\ "verb": "play",\ "timeoutSecs": 10,\ "seekOffset": 8000,\ "actionHook": "/play/action"\ }\ ]' } }); t.ok(result.statusCode === 400, 'Cant create application with invalid app_json'); /* add an application */ result = await request.post('/Applications', { resolveWithFullResponse: true, auth: authAdmin, json: true, body: { name: 'daveh', account_sid, call_hook: { url: 'http://example.com' }, call_status_hook: { url: 'http://example.com/status', method: 'POST' }, messaging_hook: { url: 'http://example.com/sms' }, app_json : '[\ {\ "verb": "play",\ "url": "https://example.com/example.mp3",\ "timeoutSecs": 10,\ "seekOffset": 8000,\ "actionHook": "/play/action"\ }\ ]', use_for_fallback_speech: 1, fallback_speech_synthesis_vendor: 'google', fallback_speech_synthesis_language: 'en-US', fallback_speech_synthesis_voice: 'man', fallback_speech_synthesis_label: 'label1', fallback_speech_recognizer_vendor: 'google', fallback_speech_recognizer_language: 'en-US', fallback_speech_recognizer_label: 'label1' } }); t.ok(result.statusCode === 201, 'successfully created application'); const sid = result.body.sid; /* query all applications */ result = await request.get('/Applications', { auth: authAdmin, json: true, }); //console.log(`result: ${JSON.stringify(result)}`); t.ok(result.length === 1 , 'successfully queried all applications'); /* query one applications */ result = await request.get(`/Applications/${sid}`, { auth: authAdmin, json: true, }); t.ok(result.name === 'daveh' , 'successfully retrieved application by sid'); t.ok(result.messaging_hook.url === 'http://example.com/sms' , 'successfully retrieved messaging_hook from application'); t.ok(result.use_for_fallback_speech === 1, 'successfully create use_for_fallback_speech'); t.ok(result.fallback_speech_synthesis_vendor === 'google', 'successfully create fallback_speech_synthesis_vendor'); t.ok(result.fallback_speech_synthesis_language === 'en-US', 'successfully create fallback_speech_synthesis_language'); t.ok(result.fallback_speech_synthesis_voice === 'man', 'successfully create fallback_speech_synthesis_voice'); t.ok(result.fallback_speech_synthesis_label === 'label1', 'successfully create fallback_speech_synthesis_label'); t.ok(result.fallback_speech_recognizer_vendor === 'google', 'successfully create fallback_speech_recognizer_vendor'); t.ok(result.fallback_speech_recognizer_language === 'en-US', 'successfully create fallback_speech_recognizer_language'); t.ok(result.fallback_speech_recognizer_label === 'label1', 'successfully create fallback_speech_recognizer_label'); let app_json = JSON.parse(result.app_json); t.ok(app_json[0].verb === 'play', 'successfully retrieved app_json from application') /* query one application by name*/ result = await request.get(`/Applications`, { qs : { name: 'daveh' }, auth: authAdmin, json: true, }); t.ok(result.length === 1 && result[0].name === 'daveh', 'successfully queried application by name'); /* query application with invalid name*/ result = await request.get(`/Applications`, { qs : { name: 'daveh-invalid' }, auth: authAdmin, json: true, }); t.ok(result.length === 0, 'successfully queried application by invalid name, no results found'); /* update applications */ result = await request.put(`/Applications/${sid}`, { auth: authAdmin, json: true, resolveWithFullResponse: true, body: { call_hook: { url: 'http://example2.com' }, messaging_hook: { url: 'http://example2.com/mms' }, app_json : '[\ {\ "verb": "hangup",\ "headers": {\ "X-Reason" : "maximum call duration exceeded"\ }\ }\ ]', record_all_calls: true, use_for_fallback_speech: 0, fallback_speech_synthesis_vendor: 'microsoft', fallback_speech_synthesis_language: 'en-US', fallback_speech_synthesis_voice: 'woman', fallback_speech_synthesis_label: 'label2', fallback_speech_recognizer_vendor: 'microsoft', fallback_speech_recognizer_language: 'en-US', fallback_speech_recognizer_label: 'label2' } }); t.ok(result.statusCode === 204, 'successfully updated application'); /* validate messaging hook was updated */ result = await request.get(`/Applications/${sid}`, { auth: authAdmin, json: true, }); t.ok(result.messaging_hook.url === 'http://example2.com/mms' , 'successfully updated messaging_hook'); app_json = JSON.parse(result.app_json); t.ok(app_json[0].verb === 'hangup', 'successfully updated app_json from application') t.ok(result.record_all_calls === 1, 'successfully updated record_all_calls from application') t.ok(result.use_for_fallback_speech === 0, 'successfully update use_for_fallback_speech'); t.ok(result.fallback_speech_synthesis_vendor === 'microsoft', 'successfully update fallback_speech_synthesis_vendor'); t.ok(result.fallback_speech_synthesis_language === 'en-US', 'successfully update fallback_speech_synthesis_language'); t.ok(result.fallback_speech_synthesis_voice === 'woman', 'successfully update fallback_speech_synthesis_voice'); t.ok(result.fallback_speech_synthesis_label === 'label2', 'successfully update fallback_speech_synthesis_label'); t.ok(result.fallback_speech_recognizer_vendor === 'microsoft', 'successfully update fallback_speech_recognizer_vendor'); t.ok(result.fallback_speech_recognizer_language === 'en-US', 'successfully update fallback_speech_recognizer_language'); t.ok(result.fallback_speech_recognizer_label === 'label2', 'successfully update fallback_speech_recognizer_label'); /* remove applications app_json*/ result = await request.put(`/Applications/${sid}`, { auth: authAdmin, json: true, resolveWithFullResponse: true, body: { call_hook: { url: 'http://example2.com' }, messaging_hook: { url: 'http://example2.com/mms' }, app_json : null } }); t.ok(result.statusCode === 204, 'successfully updated application'); /* validate messaging hook was updated */ result = await request.get(`/Applications/${sid}`, { auth: authAdmin, json: true, }); t.ok(result.app_json == undefined, 'successfully removed app_json from application') /* Update invalid applications app_json*/ result = await request.put(`/Applications/${sid}`, { auth: authAdmin, json: true, resolveWithFullResponse: true, simple: false, body: { call_hook: { url: 'http://example2.com' }, messaging_hook: { url: 'http://example2.com/mms' }, app_json : '[\ {\ "verb": "play",\ "timeoutSecs": 10,\ "seekOffset": 8000,\ "actionHook": "/play/action"\ }\ ]' } }); t.ok(result.statusCode === 400, 'Cant update invalid application app_json'); /* assign phone number to application */ result = await request.put(`/PhoneNumbers/${phone_number_sid}`, { auth: authAdmin, json: true, resolveWithFullResponse: true, body: { application_sid: sid, account_sid } }); t.ok(result.statusCode === 204, 'successfully assigned phone number to application'); /* delete application */ result = await request.delete(`/Applications/${sid}`, { auth: authAdmin, resolveWithFullResponse: true, simple: false, json: true }); //console.log(results); t.ok(result.statusCode === 422, 'cannot delete application with phone numbers'); /* delete application */ await request.delete(`/PhoneNumbers/${phone_number_sid}`, {auth: authAdmin}); result = await request.delete(`/Applications/${sid}`, { auth: authAdmin, resolveWithFullResponse: true, }); //console.log(result); t.ok(result.statusCode === 204, 'successfully deleted application after removing phone number'); await deleteObjectBySid(request, '/Accounts', account_sid); await deleteObjectBySid(request, '/VoipCarriers', voip_carrier_sid); await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid); //t.end(); } catch (err) { //console.error(err); t.end(err); } }); test('application query optimization tests', async(t) => { const app = require('../app'); try { let result; /* Create multiple service providers and accounts to test filtering */ const voip_carrier_sid = await createVoipCarrier(request, 'test-carrier-apps'); const service_provider_sid_1 = await createServiceProvider(request, 'test-sp-1'); const service_provider_sid_2 = await createServiceProvider(request, 'test-sp-2'); const account_sid_1 = await createAccount(request, service_provider_sid_1, 'test-account-1'); const account_sid_2 = await createAccount(request, service_provider_sid_2, 'test-account-2'); /* Create applications for different accounts */ const app1_result = await request.post('/Applications', { auth: authAdmin, json: true, body: { name: 'test-app-account-1', account_sid: account_sid_1, call_hook: { url: 'http://example.com/app1' }, call_status_hook: { url: 'http://example.com/app1/status' } } }); const app1_sid = app1_result.sid; const app2_result = await request.post('/Applications', { auth: authAdmin, json: true, body: { name: 'test-app-account-2', account_sid: account_sid_2, call_hook: { url: 'http://example.com/app2' }, call_status_hook: { url: 'http://example.com/app2/status' } } }); const app2_sid = app2_result.sid; const app3_result = await request.post('/Applications', { auth: authAdmin, json: true, body: { name: 'another-app-account-1', account_sid: account_sid_1, call_hook: { url: 'http://example.com/app3' }, call_status_hook: { url: 'http://example.com/app3/status' } } }); const app3_sid = app3_result.sid; /* Test 1: Query all applications as admin (no filter) - tests WHERE 1=1 fallback */ result = await request.get('/Applications', { auth: authAdmin, json: true, }); t.ok(result.length >= 3, 'admin can see all applications using WHERE 1=1'); const ourApps = result.filter(app => [app1_sid, app2_sid, app3_sid].includes(app.application_sid) ); t.ok(ourApps.length === 3, 'all three test applications are included in results'); /* Test 2: Query applications with name filter (LIKE query) - tests WHERE name LIKE optimization */ result = await request.get('/Applications', { qs: { name: 'test-app' }, auth: authAdmin, json: true, }); t.ok(result.length === 2, 'successfully filtered applications by name prefix'); t.ok(result.every(app => app.name.includes('test-app')), 'all results match name filter'); /* Test 3: Query applications with exact name match - tests WHERE optimization */ result = await request.get('/Applications', { qs: { name: 'test-app-account-1' }, auth: authAdmin, json: true, }); t.ok(result.length === 1, 'successfully filtered applications by exact name'); t.ok(result[0].name === 'test-app-account-1', 'exact name match works correctly'); /* Test 4: Query with name filter that matches nothing */ result = await request.get('/Applications', { qs: { name: 'nonexistent-app-12345' }, auth: authAdmin, json: true, }); t.ok(result.length === 0, 'non-matching name filter returns empty array'); /* Test 5: Query with pagination and name filter - tests countAll optimization */ result = await request.get('/Applications', { qs: { name: 'test-app', page: 1, page_size: 10 }, auth: authAdmin, json: true, }); t.ok(result.data.length === 2, 'pagination with name filter returns correct count'); t.ok(result.total === 2, 'countAll with name filter returns correct total'); t.ok(result.page === 1, 'pagination returns correct page number'); t.ok(result.page_size === 10, 'pagination returns correct page size'); /* Test 6: Query with pagination and no filter - tests WHERE 1=1 fallback */ result = await request.get('/Applications', { qs: { page: 1, page_size: 2 }, auth: authAdmin, json: true, }); t.ok(result.data.length === 2, 'pagination without filter returns page_size results'); t.ok(result.total >= 3, 'pagination without filter uses WHERE 1=1 and returns all'); /* Test 7: Create SP-scoped token and verify WHERE service_provider_sid optimization */ const sp1_token_result = await request.post('/ApiKeys', { auth: authAdmin, json: true, body: { service_provider_sid: service_provider_sid_1 } }); const sp1_token = sp1_token_result.token; const sp1_token_sid = sp1_token_result.sid; result = await request.get('/Applications', { auth: {bearer: sp1_token}, json: true, }); t.ok(result.length === 2, 'SP-scoped token sees only their applications via WHERE service_provider_sid'); t.ok(result.every(app => app.account_sid === account_sid_1), 'all apps belong to SP1 accounts'); /* Test 8: SP-scoped token with name filter - tests combined WHERE clause */ result = await request.get('/Applications', { qs: { name: 'test-app' }, auth: {bearer: sp1_token}, json: true, }); t.ok(result.length === 1, 'SP-scoped token with name filter combines filters correctly'); t.ok(result[0].name === 'test-app-account-1', 'combined filter returns correct app'); /* Test 9: SP-scoped token with pagination - tests countAll with service_provider_sid */ result = await request.get('/Applications', { qs: { page: 1, page_size: 10 }, auth: {bearer: sp1_token}, json: true, }); t.ok(result.data.length === 2, 'SP-scoped pagination returns correct count'); t.ok(result.total === 2, 'countAll with service_provider_sid returns correct total'); /* Cleanup tokens */ await deleteObjectBySid(request, '/ApiKeys', sp1_token_sid); /* Cleanup */ await deleteObjectBySid(request, '/Applications', app1_sid); await deleteObjectBySid(request, '/Applications', app2_sid); await deleteObjectBySid(request, '/Applications', app3_sid); await deleteObjectBySid(request, '/Accounts', account_sid_1); await deleteObjectBySid(request, '/Accounts', account_sid_2); await deleteObjectBySid(request, '/VoipCarriers', voip_carrier_sid); await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid_1); await deleteObjectBySid(request, '/ServiceProviders', service_provider_sid_2); //t.end(); } catch (err) { t.end(err); } });