Skip to content

Commit

Permalink
Merge pull request #74 from yext/dev/update-report
Browse files Browse the repository at this point in the history
EventsSdk: Update report return type
  • Loading branch information
ejaffee01 committed Sep 15, 2023
2 parents acc3977 + 075f0f9 commit f2594aa
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 177 deletions.
4 changes: 2 additions & 2 deletions docs/analytics.analyticseventservice.report.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Reports an analytics event. Operand will throw an error if the request fails. Th
<b>Signature:</b>

```typescript
report(payload?: PartialPayload): Promise<boolean | EventAPIResponse>;
report(payload?: PartialPayload): Promise<string>;
```

## Parameters
Expand All @@ -20,5 +20,5 @@ report(payload?: PartialPayload): Promise<boolean | EventAPIResponse>;

<b>Returns:</b>

Promise&lt;boolean \| [EventAPIResponse](./analytics.eventapiresponse.md)<!-- -->&gt;
Promise&lt;string&gt;

13 changes: 0 additions & 13 deletions docs/analytics.eventapiresponse.errors.md

This file was deleted.

13 changes: 0 additions & 13 deletions docs/analytics.eventapiresponse.id.md

This file was deleted.

21 changes: 0 additions & 21 deletions docs/analytics.eventapiresponse.md

This file was deleted.

1 change: 0 additions & 1 deletion docs/analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
| --- | --- |
| [AnalyticsConfig](./analytics.analyticsconfig.md) | The main configuration options for Analytics Events. |
| [AnalyticsEventService](./analytics.analyticseventservice.md) | A service for reporting Yext analytics events |
| [EventAPIResponse](./analytics.eventapiresponse.md) | Response from an analytics request. |
| [EventPayload](./analytics.eventpayload.md) | The payload accepted by the Analytics Events API. |

## Type Aliases
Expand Down
8 changes: 1 addition & 7 deletions etc/analytics.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface AnalyticsConfig {

// @public
export interface AnalyticsEventService {
report(payload?: PartialPayload): Promise<boolean | EventAPIResponse>;
report(payload?: PartialPayload): Promise<string>;
with(payload: EventPayload): AnalyticsEventService;
}

Expand All @@ -39,12 +39,6 @@ export enum EnvironmentEnum {
Sandbox = "SANDBOX"
}

// @public
export interface EventAPIResponse {
errors?: string[];
id: string;
}

// @public
export interface EventPayload {
action: Action;
Expand Down
29 changes: 14 additions & 15 deletions src/AnalyticsEventReporter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AnalyticsEventService } from './AnalyticsEventService';
import { AnalyticsConfig } from './AnalyticsConfig';
import { EventPayload, PartialPayload } from './EventPayload';
import { EventAPIResponse } from './EventAPIResponse';
import { getOrSetupSessionId } from './setupSessionId';
import packageinfo from '../package.json';
import { postWithBeacon, postWithFetch, useBeacon } from './post';
Expand Down Expand Up @@ -34,7 +33,7 @@ export class AnalyticsEventReporter implements AnalyticsEventService {
return new AnalyticsEventReporter(this.config, currentPayload);
}

public async report(newPayload?: PartialPayload): Promise<boolean | EventAPIResponse> {
public async report(newPayload?: PartialPayload): Promise<string> {
const finalPayload: EventPayload = merge(this.payload ?? {}, newPayload ?? {});

/** If session tracking is disabled, set sessionId to undefined. If it is,
Expand All @@ -60,22 +59,22 @@ export class AnalyticsEventReporter implements AnalyticsEventService {
const shouldUseBeacon = useBeacon(finalPayload, this.config.forceFetch);
const requestUrl = setupRequestUrl(this.config.env, this.config.region);

// If useBeacon returns true, return boolean response of postWithBeacon
// If useBeacon returns true, return boolean response of postWithBeacon as string.
if (shouldUseBeacon) {
return await postWithBeacon(requestUrl, finalPayload);
return new Promise((resolve, reject) => {
if (postWithBeacon(requestUrl, finalPayload)) {
resolve('');
} else {
reject('Failed Beacon Call');
}
});
}

/** If useBeacon returns false, use postWithFetch.
If result is successful, return result json.
If request fails, return errors. */
const res = await postWithFetch(requestUrl, finalPayload);
if (!res?.ok) {
const body: EventAPIResponse = await res?.json();
let errorMessage = `Events API responded with ${res?.status}: ${res?.statusText}`;
body?.errors?.forEach(e => errorMessage += `\nError: ${e}.`);
throw new Error(errorMessage);
}
const resJson = await res?.json();
return resJson;
If result is successful, return result json.
If request fails, return errors. */
return postWithFetch(requestUrl, finalPayload)
.then((response) => response)
.catch((e) => e);
}
}
9 changes: 4 additions & 5 deletions src/AnalyticsEventService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {EventAPIResponse} from './EventAPIResponse';
import {EventPayload, PartialPayload} from './EventPayload';

/**
/**
* A service for reporting Yext analytics events
*
* @public
*
* @public
*/
export interface AnalyticsEventService {
/**
Expand All @@ -26,5 +25,5 @@ export interface AnalyticsEventService {
* @param payload - desired values to be applied. The new payload will
* override any overlapping values.
*/
report(payload?: PartialPayload): Promise<boolean | EventAPIResponse>
report(payload?: PartialPayload): Promise<string>
}
15 changes: 0 additions & 15 deletions src/EventAPIResponse.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ export * from './AnalyticsEventService';
export * from './Environment';
export * from './Region';
export * from './EventPayload';
export * from './EventAPIResponse';
export * from './EnumOrString';
export * from './Action'
export * from './Action';
97 changes: 14 additions & 83 deletions tests/AnalyticsEventReporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ describe('Test report function', () => {
destinationUrl: 'https://google.com',
});


// Expect true to be returned for beacon request
expect(res).toEqual(true);
expect(res).toEqual('');
/** Expect merge to have completed correctly, the url to be constructed correctly,
and the clientSdk and authorization to be added to the request body in the correct format. **/
expect(mockPostWithBeacon).toHaveBeenCalledWith(
Expand All @@ -97,23 +98,7 @@ describe('Test report function', () => {
it('should call postWithFetch with correct fields, ' +
'report should return success json if post returns successful',
async () => {
mockPostWithFetch.mockResolvedValue({
ok: true,
status: 202,
statusText: 'OK',
json: jest.fn().mockResolvedValue({id: 1111}),
redirected: false,
type: 'basic',
url: 'https://example.com',
clone: jest.fn(),
headers: new Headers(),
body: null,
bodyUsed: false,
arrayBuffer: jest.fn(),
blob: jest.fn(),
formData: jest.fn(),
text: jest.fn()
});
mockPostWithFetch.mockResolvedValue({id: 1111});
mockUseBeacon.mockReturnValueOnce(false);

const config: AnalyticsConfig = {
Expand Down Expand Up @@ -154,24 +139,7 @@ describe('Test report function', () => {
const mockSetupSessionId = getOrSetupSessionId as jest.MockedFunction<typeof getOrSetupSessionId>;

mockSetupSessionId.mockImplementation( () => 'ULID1234');

mockPostWithFetch.mockResolvedValue({
ok: true,
status: 401,
statusText: 'Unauthorized request',
json: jest.fn().mockResolvedValue({id: 1111, errors: ['Unauthorized request']}),
redirected: false,
type: 'basic',
url: 'https://example.com',
clone: jest.fn(),
headers: new Headers(),
body: null,
bodyUsed: false,
arrayBuffer: jest.fn(),
blob: jest.fn(),
formData: jest.fn(),
text: jest.fn()
});
mockPostWithFetch.mockRejectedValue({id: 1111, errors: ['Unauthorized request']});
mockUseBeacon.mockReturnValueOnce(false);

const config: AnalyticsConfig = {
Expand Down Expand Up @@ -220,25 +188,8 @@ describe('Test report function', () => {
it('should call post with correct fields, should set sessionId undefined if session tracking disabled',
async () => {
const mockSetupSessionId = getOrSetupSessionId as jest.MockedFunction<typeof getOrSetupSessionId>;

mockPostWithFetch.mockResolvedValue({
ok: true,
status: 202,
statusText: 'Unauthorized request',
json: jest.fn().mockResolvedValue({id: 1111}),
redirected: false,
type: 'basic',
url: 'https://example.com',
clone: jest.fn(),
headers: new Headers(),
body: null,
bodyUsed: false,
arrayBuffer: jest.fn(),
blob: jest.fn(),
formData: jest.fn(),
text: jest.fn()
});
mockUseBeacon.mockReturnValueOnce(false);
mockPostWithFetch.mockResolvedValue({id: 1111});

const config: AnalyticsConfig = {
bearer: 'bearerToken',
Expand Down Expand Up @@ -304,7 +255,7 @@ describe('Test report function', () => {
const res = await reporter.report();

// Expect true to be returned for beacon request
expect(res).toEqual(true);
expect(res).toEqual('');
/** Expect merge to have completed correctly, the url to be constructed correctly,
and the clientSdk and authorization to be added to the request body in the correct format. **/
expect(mockPostWithBeacon).toHaveBeenCalledWith(
Expand Down Expand Up @@ -341,7 +292,7 @@ describe('Test report function', () => {
count: 5});

// Expect true to be returned for beacon request
expect(res).toEqual(true);
expect(res).toEqual('');
/** Expect merge to have completed correctly, the url to be constructed correctly,
and the clientSdk and authorization to be added to the request body in the correct format. **/
expect(mockPostWithBeacon).toHaveBeenCalledWith(
Expand All @@ -359,27 +310,11 @@ describe('Test report function', () => {

it('calling report with no argument and no with call should result in invalid request body and error',
async () => {
mockPostWithFetch.mockResolvedValue({
ok: false,
status: 400,
statusText: 'Bad Request',
json: jest.fn().mockResolvedValue({}),
redirected: false,
type: 'basic',
url: 'https://example.com',
clone: jest.fn(),
headers: new Headers(),
body: null,
bodyUsed: false,
arrayBuffer: jest.fn(),
blob: jest.fn(),
formData: jest.fn(),
text: jest.fn()
});
mockPostWithBeacon.mockReturnValue(false);
mockPostWithFetch.mockRejectedValue({errors: ['Bad Request']});

const navigator = { userAgent: 'Chrome', sendBeacon: () => { return false; }};
Object.defineProperty(window, 'navigator', { value: navigator, writable: true});
mockPostWithBeacon.mockReturnValue(false);

const config: AnalyticsConfig = {
key: 'validKey',
Expand All @@ -389,13 +324,9 @@ describe('Test report function', () => {

const service: AnalyticsEventService = new AnalyticsEventReporter(config);

try {
await service.report({});
// Fail test if above expression doesn't throw anything.
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe('Events API responded with 400: Bad Request');
}
const res = await service.report({});
expect(res).toEqual({errors: ['Bad Request']});


/** Expect merge to have completed correctly, but the request
* body to be invalid as action was never added **/
Expand Down Expand Up @@ -430,7 +361,7 @@ describe('Test report function', () => {

const res1 = await reporter1.report();
// Expect true to be returned for beacon request
expect(res1).toEqual(true);
expect(res1).toEqual('');
expect(mockPostWithBeacon).toHaveBeenCalledWith(
'https://eu.yextevents.com/accounts/me/events',
{
Expand All @@ -457,7 +388,7 @@ describe('Test report function', () => {
const res2 = await reporter2.report();

// Expect true to be returned for beacon request
expect(res2).toEqual(true);
expect(res2).toEqual('');
/** Expect merge to have completed correctly, the url to be constructed correctly,
and the clientSdk and authorization to be added to the request body in the correct format. **/
expect(mockPostWithBeacon).toHaveBeenCalledWith(
Expand Down

0 comments on commit f2594aa

Please sign in to comment.