forked from segmentio/action-destinations
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DOTORG-839: Blackbaud Raiser's Edge NXT Destination (segmentio#998)
* DOTORG-839: Create or Update Individual Constituent Action (#1) * DOTORG-839 Added OAuth2 settings for Blackbaud (#2) * Move bbApiSubscriptionKey to settings * Only aggregate integrationErrors * Update Online Presence label * Update directory structure * Add types * Abstract API calls * Add dateStringToFuzzyDate * Add types * Don't retry 401s * Don't catch errors on constituent search or creation * Concatenate integrationErrors * Add throwHttpErrors * Set default for lookup_id to userId * Pass constituentId to updateConstituent * Remove try/catch * Use camelCase traits * Add filterObjectListByMatchFields * Check if primary property is defined * DOTORG-839 Added authentication test (#3) * Don't match on country * Use datetime type * Strip non-numeric characters from phone when matching * Don't match on undefined boolean fields * Update generated-types.ts * Fix linting errors * Move fixtures out of tests directory * Update constituentData * Update default lookup_id mapping * Update testAuthentication * Remove UNEXPECTED_RECORD_COUNT error * Update tests --------- Co-authored-by: twilio-hwong <[email protected]>
- Loading branch information
1 parent
4fbbdab
commit e7baeb0
Showing
15 changed files
with
2,164 additions
and
0 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
...src/destinations/blackbaud-raisers-edge-nxt/__tests__/__snapshots__/snapshot.test.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Testing snapshot for actions-blackbaud-raisers-edge-nxt destination: createOrUpdateIndividualConstituent action - all fields 1`] = `""`; | ||
|
||
exports[`Testing snapshot for actions-blackbaud-raisers-edge-nxt destination: createOrUpdateIndividualConstituent action - required fields 1`] = `""`; | ||
|
||
exports[`Testing snapshot for actions-blackbaud-raisers-edge-nxt destination: createOrUpdateIndividualConstituent action - required fields 2`] = ` | ||
Headers { | ||
Symbol(map): Object { | ||
"authorization": Array [ | ||
"Bearer undefined", | ||
], | ||
"bb-api-subscription-key": Array [ | ||
"hUXnkT]ixm7mm*HX", | ||
], | ||
"user-agent": Array [ | ||
"Segment (Actions)", | ||
], | ||
}, | ||
} | ||
`; |
21 changes: 21 additions & 0 deletions
21
...s/destination-actions/src/destinations/blackbaud-raisers-edge-nxt/__tests__/index.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import nock from 'nock' | ||
// import { createTestEvent, createTestIntegration } from '@segment/actions-core' | ||
import { createTestIntegration } from '@segment/actions-core' | ||
import { SKY_API_BASE_URL } from '../constants' | ||
import Definition from '../index' | ||
|
||
const testDestination = createTestIntegration(Definition) | ||
|
||
describe("Blackbaud Raiser's Edge NXT", () => { | ||
describe('testAuthentication', () => { | ||
it('should validate authentication inputs', async () => { | ||
nock(SKY_API_BASE_URL).get('/emailaddresstypes').reply(200, {}) | ||
|
||
const settings = { | ||
bbApiSubscriptionKey: 'subscription_key' | ||
} | ||
|
||
await expect(testDestination.testAuthentication(settings)).resolves.not.toThrowError() | ||
}) | ||
}) | ||
}) |
81 changes: 81 additions & 0 deletions
81
...estination-actions/src/destinations/blackbaud-raisers-edge-nxt/__tests__/snapshot.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { createTestEvent, createTestIntegration } from '@segment/actions-core' | ||
import { generateTestData } from '../../../lib/test-data' | ||
import destination from '../index' | ||
import nock from 'nock' | ||
|
||
const testDestination = createTestIntegration(destination) | ||
const destinationSlug = 'actions-blackbaud-raisers-edge-nxt' | ||
|
||
describe(`Testing snapshot for ${destinationSlug} destination:`, () => { | ||
for (const actionSlug in destination.actions) { | ||
it(`${actionSlug} action - required fields`, async () => { | ||
const seedName = `${destinationSlug}#${actionSlug}` | ||
const action = destination.actions[actionSlug] | ||
const [eventData, settingsData] = generateTestData(seedName, destination, action, true) | ||
|
||
eventData.last = 'Smith' | ||
|
||
nock(/.*/).persist().get(/.*/).reply(200, {}) | ||
nock(/.*/).persist().patch(/.*/).reply(200, {}) | ||
nock(/.*/).persist().post(/.*/).reply(200, {}) | ||
nock(/.*/).persist().put(/.*/).reply(200, {}) | ||
|
||
const event = createTestEvent({ | ||
properties: eventData | ||
}) | ||
|
||
const responses = await testDestination.testAction(actionSlug, { | ||
event: event, | ||
mapping: event.properties, | ||
settings: settingsData, | ||
auth: undefined | ||
}) | ||
|
||
const request = responses[0].request | ||
const rawBody = await request.text() | ||
|
||
try { | ||
const json = JSON.parse(rawBody) | ||
expect(json).toMatchSnapshot() | ||
return | ||
} catch (err) { | ||
expect(rawBody).toMatchSnapshot() | ||
} | ||
|
||
expect(request.headers).toMatchSnapshot() | ||
}) | ||
|
||
it(`${actionSlug} action - all fields`, async () => { | ||
const seedName = `${destinationSlug}#${actionSlug}` | ||
const action = destination.actions[actionSlug] | ||
const [eventData, settingsData] = generateTestData(seedName, destination, action, false) | ||
|
||
nock(/.*/).persist().get(/.*/).reply(200, {}) | ||
nock(/.*/).persist().patch(/.*/).reply(200, {}) | ||
nock(/.*/).persist().post(/.*/).reply(200, {}) | ||
nock(/.*/).persist().put(/.*/).reply(200, {}) | ||
|
||
const event = createTestEvent({ | ||
properties: eventData | ||
}) | ||
|
||
const responses = await testDestination.testAction(actionSlug, { | ||
event: event, | ||
mapping: event.properties, | ||
settings: settingsData, | ||
auth: undefined | ||
}) | ||
|
||
const request = responses[0].request | ||
const rawBody = await request.text() | ||
|
||
try { | ||
const json = JSON.parse(rawBody) | ||
expect(json).toMatchSnapshot() | ||
return | ||
} catch (err) { | ||
expect(rawBody).toMatchSnapshot() | ||
} | ||
}) | ||
} | ||
}) |
156 changes: 156 additions & 0 deletions
156
packages/destination-actions/src/destinations/blackbaud-raisers-edge-nxt/api/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import type { RequestClient, ModifiedResponse } from '@segment/actions-core' | ||
import { SKY_API_BASE_URL } from '../constants' | ||
|
||
export class BlackbaudSkyApi { | ||
request: RequestClient | ||
|
||
constructor(request: RequestClient) { | ||
this.request = request | ||
} | ||
|
||
async getExistingConstituents(searchField: string, searchText: string): Promise<ModifiedResponse> { | ||
return this.request( | ||
`${SKY_API_BASE_URL}/constituents/search?search_field=${searchField}&search_text=${searchText}`, | ||
{ | ||
method: 'get' | ||
} | ||
) | ||
} | ||
|
||
async createConstituent(constituentData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/constituents`, { | ||
method: 'post', | ||
json: constituentData | ||
}) | ||
} | ||
|
||
async updateConstituent(constituentId: string, constituentData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/constituents/${constituentId}`, { | ||
method: 'patch', | ||
json: constituentData, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async getConstituentAddressList(constituentId: string): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/constituents/${constituentId}/addresses?include_inactive=true`, { | ||
method: 'get', | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async createConstituentAddress(constituentId: string, constituentAddressData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/addresses`, { | ||
method: 'post', | ||
json: { | ||
...constituentAddressData, | ||
constituent_id: constituentId | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async updateConstituentAddressById(addressId: string, constituentAddressData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/addresses/${addressId}`, { | ||
method: 'patch', | ||
json: { | ||
...constituentAddressData, | ||
inactive: false | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async getConstituentEmailList(constituentId: string): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/constituents/${constituentId}/emailaddresses?include_inactive=true`, { | ||
method: 'get', | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async createConstituentEmail(constituentId: string, constituentEmailData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/emailaddresses`, { | ||
method: 'post', | ||
json: { | ||
...constituentEmailData, | ||
constituent_id: constituentId | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async updateConstituentEmailById(emailId: string, constituentEmailData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/emailaddresses/${emailId}`, { | ||
method: 'patch', | ||
json: { | ||
...constituentEmailData, | ||
inactive: false | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async getConstituentOnlinePresenceList(constituentId: string): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/constituents/${constituentId}/onlinepresences?include_inactive=true`, { | ||
method: 'get', | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async createConstituentOnlinePresence( | ||
constituentId: string, | ||
constituentOnlinePresenceData: object | ||
): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/onlinepresences`, { | ||
method: 'post', | ||
json: { | ||
...constituentOnlinePresenceData, | ||
constituent_id: constituentId | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async updateConstituentOnlinePresenceById( | ||
onlinePresenceId: string, | ||
constituentOnlinePresenceData: object | ||
): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/onlinepresences/${onlinePresenceId}`, { | ||
method: 'patch', | ||
json: { | ||
...constituentOnlinePresenceData, | ||
inactive: false | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async getConstituentPhoneList(constituentId: string): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/constituents/${constituentId}/phones?include_inactive=true`, { | ||
method: 'get', | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async createConstituentPhone(constituentId: string, constituentPhoneData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/phones`, { | ||
method: 'post', | ||
json: { | ||
...constituentPhoneData, | ||
constituent_id: constituentId | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
|
||
async updateConstituentPhoneById(phoneId: string, constituentPhoneData: object): Promise<ModifiedResponse> { | ||
return this.request(`${SKY_API_BASE_URL}/phones/${phoneId}`, { | ||
method: 'patch', | ||
json: { | ||
...constituentPhoneData, | ||
inactive: false | ||
}, | ||
throwHttpErrors: false | ||
}) | ||
} | ||
} |
2 changes: 2 additions & 0 deletions
2
packages/destination-actions/src/destinations/blackbaud-raisers-edge-nxt/constants/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const SKY_API_BASE_URL = 'https://api.sky.blackbaud.com/constituent/v1' | ||
export const SKY_OAUTH2_TOKEN_URL = 'https://oauth2.sky.blackbaud.com/token' |
21 changes: 21 additions & 0 deletions
21
...dge-nxt/createOrUpdateIndividualConstituent/__tests__/__snapshots__/snapshot.test.ts.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Testing snapshot for BlackbaudRaisersEdgeNxt's createOrUpdateIndividualConstituent destination action: all fields 1`] = `""`; | ||
|
||
exports[`Testing snapshot for BlackbaudRaisersEdgeNxt's createOrUpdateIndividualConstituent destination action: required fields 1`] = `""`; | ||
|
||
exports[`Testing snapshot for BlackbaudRaisersEdgeNxt's createOrUpdateIndividualConstituent destination action: required fields 2`] = ` | ||
Headers { | ||
Symbol(map): Object { | ||
"authorization": Array [ | ||
"Bearer undefined", | ||
], | ||
"bb-api-subscription-key": Array [ | ||
"H*Z39ROa", | ||
], | ||
"user-agent": Array [ | ||
"Segment (Actions)", | ||
], | ||
}, | ||
} | ||
`; |
Oops, something went wrong.