Skip to content

Commit

Permalink
other: Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
olexandr-mazepa committed Dec 26, 2024
1 parent de16ccd commit 78f9990
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 81 deletions.
1 change: 1 addition & 0 deletions dist/Classes/Metrics/MetricsClient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default class MetricsClient implements IMetricsClient {
constructor(request: Request, logger?: ILogger);
private convertDateToUTC;
private prepareQuery;
private handleResponse;
getAccount(query?: MetricsQuery): Promise<MetricsResult>;
getAccountUsage(query?: MetricsQuery): Promise<MetricsResult>;
}
106 changes: 53 additions & 53 deletions dist/Types/Metrics/Metrics.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Resolution } from '../../Enums';
export type MetricsFilterValue = {
label: string;
label?: string;
value: string;
};
export type MetricsFilter = {
Expand All @@ -9,8 +9,8 @@ export type MetricsFilter = {
values: MetricsFilterValue[];
};
export type MetricsQuery = {
start?: Date;
end?: Date;
start?: Date | string;
end?: Date | string;
resolution?: Resolution;
duration?: string;
dimensions?: string[];
Expand All @@ -22,53 +22,53 @@ export type MetricsQuery = {
include_aggregates?: boolean;
};
export type Metrics = {
accepted_outgoing_count: number;
delivered_smtp_count: number;
accepted_count: number;
delivered_http_count: number;
accepted_incoming_count: number;
delivered_optimized_count: number;
stored_count: number;
delivered_count: number;
processed_count: number;
sent_count: number;
opened_count: number;
unique_opened_count: number;
clicked_count: number;
unique_clicked_count: number;
complained_count: number;
permanent_failed_count: number;
failed_count: number;
rate_limit_count: number;
unsubscribed_count: number;
temporary_failed_count: number;
permanent_failed_optimized_count: number;
bounced_count: number;
esp_block_count: number;
webhook_count: number;
delayed_bounce_count: number;
soft_bounces_count: number;
permanent_failed_old_count: number;
suppressed_bounces_count: number;
delivered_subsequent_count: number;
delivered_rate: string;
delayed_first_attempt_count: number;
unsubscribed_rate: string;
delivered_first_attempt_count: number;
opened_rate: string;
suppressed_complaints_count: number;
delivered_two_plus_attempts_count: number;
hard_bounces_count: number;
suppressed_unsubscribed_count: number;
unique_opened_rate: string;
fail_rate: string;
complained_rate: string;
clicked_rate: string;
unique_clicked_rate: string;
bounce_rate: string;
delayed_rate: string;
permanent_fail_rate: string;
temporary_fail_rate: string;
accepted_outgoing_count?: number;
delivered_smtp_count?: number;
accepted_count?: number;
delivered_http_count?: number;
accepted_incoming_count?: number;
delivered_optimized_count?: number;
stored_count?: number;
delivered_count?: number;
processed_count?: number;
sent_count?: number;
opened_count?: number;
unique_opened_count?: number;
clicked_count?: number;
unique_clicked_count?: number;
complained_count?: number;
permanent_failed_count?: number;
failed_count?: number;
rate_limit_count?: number;
unsubscribed_count?: number;
temporary_failed_count?: number;
permanent_failed_optimized_count?: number;
bounced_count?: number;
esp_block_count?: number;
webhook_count?: number;
delayed_bounce_count?: number;
soft_bounces_count?: number;
permanent_failed_old_count?: number;
suppressed_bounces_count?: number;
delivered_subsequent_count?: number;
delivered_rate?: string;
delayed_first_attempt_count?: number;
unsubscribed_rate?: string;
delivered_first_attempt_count?: number;
opened_rate?: string;
suppressed_complaints_count?: number;
delivered_two_plus_attempts_count?: number;
hard_bounces_count?: number;
suppressed_unsubscribed_count?: number;
unique_opened_rate?: string;
fail_rate?: string;
complained_rate?: string;
clicked_rate?: string;
unique_clicked_rate?: string;
bounce_rate?: string;
delayed_rate?: string;
permanent_fail_rate?: string;
temporary_fail_rate?: string;
};
export type MetricsPagination = {
sort: string;
Expand All @@ -88,13 +88,13 @@ export type MetricsResponseItem = {
export type MetricsResult = {
items: MetricsResponseItem[];
resolution: string;
start: string;
start: Date | null;
aggregates: {
metrics: Metrics;
};
dimensions: string[];
pagination: MetricsPagination;
end: string;
duration: string;
end: Date | null;
duration?: string;
status: number;
};
2 changes: 1 addition & 1 deletion dist/Types/Metrics/MetricsAPI.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ export type MetricsAPIResponse = {
dimensions: string[];
pagination: MetricsPagination;
end: string;
duration: string;
duration?: string;
};
};
21 changes: 14 additions & 7 deletions dist/mailgun.node.js

Large diffs are not rendered by default.

21 changes: 14 additions & 7 deletions dist/mailgun.web.js

Large diffs are not rendered by default.

23 changes: 15 additions & 8 deletions lib/Classes/Metrics/MetricsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,28 @@ Consider using string type for property "${key}" to avoid auto-converting`);
return result;
}

private handleResponse(response: MetricsAPIResponse): MetricsResult {
const resBody = response.body;
const startDate = Date.parse(resBody.start) ? new Date(resBody.start) : null;
const endDate = Date.parse(resBody.end) ? new Date(resBody.end) : null;
const result: MetricsResult = {
...resBody,
status: response.status,
start: startDate,
end: endDate
};
return result;
}

async getAccount(query?: MetricsQuery): Promise<MetricsResult> {
const queryData = this.prepareQuery(query);
const response: MetricsAPIResponse = await this.request.post('/v1/analytics/metrics', queryData);
return {
...response.body,
status: response.status
};
return this.handleResponse(response);
}

async getAccountUsage(query?: MetricsQuery): Promise<MetricsResult> {
const queryData = this.prepareQuery(query);
const response: MetricsAPIResponse = await this.request.post('/v1/analytics/usage/metrics', queryData);
return {
...response.body,
status: response.status
};
return this.handleResponse(response);
}
}
8 changes: 4 additions & 4 deletions lib/Types/Metrics/Metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Resolution } from '../../Enums';

export type MetricsFilterValue = {
label: string;
label?: string;
value: string;
}
export type MetricsFilter = {
Expand Down Expand Up @@ -96,13 +96,13 @@ export type MetricsResponseItem = {
export type MetricsResult = {
items: MetricsResponseItem[];
resolution: string;
start: string;
start: Date | null;
aggregates: {
metrics: Metrics;
}
dimensions: string[];
pagination: MetricsPagination;
end: string;
duration: string;
end: Date | null;
duration?: string;
status: number;
}
2 changes: 1 addition & 1 deletion lib/Types/Metrics/MetricsAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ export type MetricsAPIResponse = {
dimensions: string[];
pagination: MetricsPagination;
end: string;
duration: string;
duration?: string;
}
}
167 changes: 167 additions & 0 deletions test/metrics.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import formData from 'form-data';

import nock from 'nock';
import { expect } from 'chai';
import Request from '../lib/Classes/common/Request';
import { InputFormData, RequestOptions } from '../lib/Types/Common';
import { IMetricsClient } from '../lib/Interfaces/Metrics/MetricsClient';
import MetricsClient from '../lib/Classes/Metrics/MetricsClient';
import { MetricsAPIQuery, MetricsResult } from '../lib/Types/Metrics';

Check warning on line 9 in test/metrics.test.ts

View workflow job for this annotation

GitHub Actions / lint

'MetricsAPIQuery' is defined but never used
import { Resolution } from '../lib/Enums';

describe('MetricsClient', function () {
let client: IMetricsClient;
let api: nock.Scope;
const testDate = new Date();
const metricsResponse = {
start: testDate.toISOString(),
end: testDate.toISOString(),
resolution: 'hour',
dimensions: ['time'],
pagination: {
sort: '',
skip: 0,
limit: 1500,
total: 1
},
items: [
{
dimensions: [{
dimension: 'time',
value: testDate.toISOString(),
display_value: testDate.toISOString()
}],
metrics: {
delivered_count: 1,
sent_count: 1,
opened_count: 0,
failed_count: 0,
}
},
],
aggregates: { metrics: {} },
};

const expectedMetricsResponse: MetricsResult = {
...metricsResponse,
start: testDate,
end: testDate,
status: 200,
};

beforeEach(function () {
client = new MetricsClient(
new Request({ url: 'https://api.mailgun.net' } as RequestOptions, formData as InputFormData),
{
warn: () => undefined
}
);
api = nock('https://api.mailgun.net');
});

afterEach(function () {
api.done();
});

describe('getAccount', async () => {
it('fetches metrics for a given account', async () => {
api.post('/v1/analytics/metrics')
.reply(200, metricsResponse);

const result: MetricsResult = await client.getAccount();
result.should.be.an('object').to.have.property('items');
result.items.should.be.an('array').to.have.property('length').to.be.equal(1);
result.should.eql(expectedMetricsResponse);
});

it('prepares dates in query', async () => {
const startDate = new Date();
const endDate = new Date();
let updatedQuery;
const query = {
start: startDate,
end: endDate,
resolution: Resolution.HOUR,
duration: '1m',
dimensions: ['time'],
metrics: ['opened_count'],
filter: {
AND: [{
attribute: 'domain',
comparator: 'contains',
values: [{
label: 'test',
value: 'mailgun'
}]
}]
},
include_subaccounts: true,
include_aggregates: false,
};

api.post('/v1/analytics/metrics', (body) => {
updatedQuery = body;
return true;
}).reply(200, metricsResponse);

await client.getAccount(query);
expect(updatedQuery).to.be.an('object');
expect(updatedQuery).eql({
...query,
start: startDate.toUTCString(),
end: endDate.toUTCString()
});
});
});

describe('getAccountUsage', async () => {
it('fetches metrics for a given account', async () => {
api.post('/v1/analytics/usage/metrics')
.reply(200, metricsResponse);

const result: MetricsResult = await client.getAccountUsage();
result.should.be.an('object').to.have.property('items');
result.items.should.be.an('array').to.have.property('length').to.be.equal(1);
result.should.eql(expectedMetricsResponse);
});

it('prepares dates in query', async () => {
const startDate = new Date();
const endDate = new Date();
let updatedQuery;
const query = {
start: startDate,
end: endDate,
resolution: Resolution.HOUR,
duration: '1m',
dimensions: ['time'],
metrics: ['opened_count'],
filter: {
AND: [{
attribute: 'domain',
comparator: 'contains',
values: [{
label: 'test',
value: 'mailgun'
}]
}]
},
include_subaccounts: true,
include_aggregates: false,
};

api.post('/v1/analytics/usage/metrics', (body) => {
updatedQuery = body;
return true;
}).reply(200, metricsResponse);

await client.getAccountUsage(query);
expect(updatedQuery).to.be.an('object');
expect(updatedQuery).eql({
...query,
start: startDate.toUTCString(),
end: endDate.toUTCString()
});
});
});
});

0 comments on commit 78f9990

Please sign in to comment.