Skip to content

Commit 734394e

Browse files
committed
Started working on the test setup.
1 parent 7d931ad commit 734394e

File tree

5 files changed

+145
-43
lines changed

5 files changed

+145
-43
lines changed

src/Endpoints/alias-endpoints.ts

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,49 @@
1-
import { AliasDeleteRequest, AliasPostRequest, AliasResponse, AliasUpdateRequest, MailcowResponse } from '../types';
1+
import {
2+
Alias,
3+
AliasDeleteRequest,
4+
AliasPostRequest,
5+
AliasUpdateRequest,
6+
MailcowResponse
7+
} from '../types';
28
import MailcowClient from '../index';
9+
import { wrapPromiseToArray } from '../request-factory';
310

4-
export interface AliasInterface {
11+
export interface AliasEndpoints {
512
/**
6-
* Get mailbox aliases existing in system.
13+
* Endpoint for getting mailbox aliases in the system.
714
* @param id - The id of the alias you want to get. Use 'all' to retrieve all aliases in the system.
15+
*
16+
* @example Get all aliases:
17+
* ```typescript
18+
* mcc.aliases.get('all').then((res) => { console.log(res); });
19+
* ```
20+
* @example Get a single alias:
21+
* ```typescript
22+
* mcc.aliases.get(8).then((res) => { console.log(res); });
23+
* ```
824
*/
9-
get: (id?: number | 'all') => Promise<AliasResponse[] | AliasResponse>,
10-
create: any,
11-
update: any,
12-
delete: any,
25+
get: (id?: number | 'all') => Promise<Alias[]>,
26+
27+
/**
28+
* Endpoint for creating mailbox aliases.
29+
* @param payload - View {@link AliasAttributes} for payload parameters.
30+
*/
31+
create: (payload: AliasPostRequest) => Promise<MailcowResponse>,
32+
/**
33+
* Update for editing a mailbox alias.
34+
* @param payload -
35+
*/
36+
update: (payload: AliasUpdateRequest) => Promise<MailcowResponse>,
37+
delete: (payload: AliasDeleteRequest) => Promise<MailcowResponse>,
1338
}
1439

15-
export default function AliasEndpoints(bind: MailcowClient): AliasInterface {
40+
export function aliasEndpoints(bind: MailcowClient): AliasEndpoints {
1641
return {
17-
get(id = 'all'): Promise<AliasResponse[]> {
18-
return bind.requestFactory.get<AliasResponse[]>(
19-
`/api/v1/get/alias/${ id }`,
20-
);
42+
get(id = 'all'): Promise<Alias[]> {
43+
return wrapPromiseToArray<Alias>(
44+
bind.requestFactory.get<Alias[] | Alias>(
45+
`/api/v1/get/alias/${ id }`
46+
));
2147
},
2248
create: (payload: AliasPostRequest): Promise<MailcowResponse> => {
2349
return bind.requestFactory.post<MailcowResponse>(

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import domainEndpoints from './Endpoints/domain-endpoints';
77
import antiSpamEndpoints from './Endpoints/antispam-endpoints';
88
import mailboxEndpoints from './Endpoints/mailbox-endpoint';
99
import RequestFactory from './request-factory';
10-
import aliasEndpoints, { AliasInterface } from './Endpoints/alias-endpoints';
10+
import { aliasEndpoints, AliasEndpoints } from './Endpoints/alias-endpoints';
1111

1212
/**
1313
* Class containing all the logic to interface with the Mailcow API in TypeScript.
@@ -49,7 +49,7 @@ export class MailcowClient {
4949
/**
5050
* All endpoints related to Aliases.
5151
*/
52-
public aliases: AliasInterface = aliasEndpoints(this)
52+
public aliases: AliasEndpoints = aliasEndpoints(this)
5353

5454
public domains = domainEndpoints(this)
5555

src/request-factory.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@ import axios, { AxiosError, AxiosResponse } from 'axios';
22
import { MailcowErrorResponse, MailcowException, Payload } from './types';
33
import MailcowClient from './index';
44

5+
function wrapToArray<T>(item: T | T[]): T[] {
6+
return Array.isArray(item) ? item : [item];
7+
}
8+
9+
export function wrapPromiseToArray<T>(promise: Promise<T|T[]>): Promise<T[]> {
10+
return new Promise<T[]>((resolve, reject) => {
11+
promise
12+
.then((res: T | T[]) => resolve(wrapToArray(res)))
13+
.catch((err) => reject(err));
14+
});
15+
}
16+
517
/**
618
* Factory method patterns for creating Axios Requests.
719
* @internal
@@ -18,7 +30,7 @@ export default class RequestFactory {
1830
* @param route - The route to which to send the request.
1931
* @param payload - The payload to send with the request.
2032
*/
21-
async post <T>(route: string, payload: Payload): Promise<T> {
33+
async post<T>(route: string, payload: Payload): Promise<T> {
2234
return new Promise((resolve, reject) => {
2335
axios
2436
.post(this.ctx.BASE_URL + route, payload, this.ctx.HEADERS)

src/types.ts

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -220,18 +220,39 @@ export interface ACLEditRequest {
220220
}
221221

222222
export type AliasAttributes = {
223-
address: string;
223+
/**
224+
* The alias address, for catchall use "@domain.tld".
225+
*/
226+
address: string
227+
/**
228+
* The destination address, comma separated.
229+
*/
224230
goto: string;
231+
/**
232+
* If true: silently ignore.
233+
*/
225234
goto_null?: boolean;
235+
/**
236+
* If true: learn as spam.
237+
*/
226238
goto_spam?: boolean;
239+
/**
240+
* If true: learn as ham.
241+
*/
227242
goto_ham?: boolean;
243+
/**
244+
* If alias is visible in sogo.
245+
*/
228246
sogo_visible: boolean;
247+
/**
248+
* If alias is active or not.
249+
*/
229250
active: boolean;
230251
};
231252

232-
export type AliasEditAttributes = AliasAttributes & {
233-
private_comment: string;
234-
public_comment: string;
253+
export type AliasEditAttributes = Partial<AliasAttributes> & {
254+
private_comment?: string;
255+
public_comment?: string;
235256
};
236257

237258
export type AliasPostRequest = AliasAttributes;
@@ -245,18 +266,17 @@ export interface AliasDeleteRequest {
245266
items: number[];
246267
}
247268

248-
export interface AliasResponse {
249-
in_primary_domain: string;
250-
id: number;
251-
domain: string;
252-
public_comment: string;
253-
private_comment: string;
254-
goto: string;
255-
address: string;
256-
is_catch_all: boolean;
257-
active: boolean;
258-
created: string;
259-
modified: string;
269+
export interface Alias extends AliasAttributes {
270+
in_primary_domain: string,
271+
id: number,
272+
domain: string,
273+
public_comment: string,
274+
private_comment: string,
275+
is_catch_all: boolean,
276+
active_int: number,
277+
sogo_visible_int: number,
278+
created: string,
279+
modified: string | null
260280
}
261281

262282
export class MailcowException extends Error {
@@ -268,13 +288,13 @@ export class MailcowException extends Error {
268288
*
269289
* This is used when the API call doesn't return any objects, i.e. POST requests.
270290
*/
271-
export interface MailcowResponseContent {
291+
export interface BaseResponse {
272292
log?: (string | Payload)[];
273293
msg: string[] | string;
274294
type: 'succes' | 'danger' | 'error';
275295
}
276296

277-
export type MailcowResponse = MailcowResponseContent[];
297+
export type MailcowResponse<T = BaseResponse> = T[];
278298

279299
export interface MailcowErrorResponse extends MailcowResponse {
280300
msg: string;

test/index.test.ts

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,63 @@
11
import MailcowClient from "../src";
2-
import { expect } from "chai";
2+
import { expect, assert } from "chai";
33
import { describe } from "mocha";
4+
import { Alias, AliasPostRequest, MailcowResponse } from "../src/types";
5+
import { AliasEditAttributes } from "../src/types";
46

57
const mcc: MailcowClient = new MailcowClient("https://demo.mailcow.email/", "390448-22B69F-FA37D9-19701B-6F033F")
68

9+
async function thenTestOrFail(promise: Promise<any>, test: Function): Promise<void> {
10+
await promise.then((res: any) => {
11+
test(res);
12+
}).catch((err) => {
13+
assert.fail('expected', 'actual', err);
14+
});
15+
}
16+
717
describe("Alias Endpoint tests", (): void => {
8-
it('should get all aliases', (): void => {
9-
mcc.aliases.get().then((res) => {
10-
expect(res).to.be.length.least(1)
11-
})
18+
it('should get all aliases', async () => {
19+
await thenTestOrFail(mcc.aliases.get(), (res: Alias[]) => expect(res).to.be.length.least(1))
1220
});
13-
it('should get a single alias', (): void => {
14-
mcc.aliases.get(8).then((res) => {
15-
expect(res).to.be.length(1)
16-
})
21+
it('should get a single alias', async () => {
22+
await thenTestOrFail(mcc.aliases.get(8), (res: Alias[]) => expect(res).to.be.length.least(1))
1723
});
24+
describe("Modify aliases", (): void => {
25+
const attr: AliasPostRequest = {
26+
active: true,
27+
address: "ts-mailcow-api@440044.xyz",
28+
goto: "demo@440044.xyz",
29+
sogo_visible: true,
30+
}
31+
const editAttr: AliasEditAttributes = {
32+
active: false,
33+
address: "ts-mailcow-api-edit@440044.xyz",
34+
goto: "demo-edit@440044.xyz",
35+
private_comment: "private comment",
36+
public_comment: "public comment",
37+
sogo_visible: false,
38+
}
39+
let id: number;
40+
it('should create an alias', async () => {
41+
await thenTestOrFail(mcc.aliases.create(attr), (res: MailcowResponse) => {
42+
expect(res[0].type).to.be.equal("success")
43+
id = parseInt(res[0].msg[2])
44+
})
45+
});
46+
it('should delete edit previously created alias', async () => {
47+
await thenTestOrFail(mcc.aliases.update({ attr: editAttr, items: [id] }), (res: MailcowResponse) => {
48+
expect(res[0].type).to.be.equal("success")
49+
})
50+
await thenTestOrFail(mcc.aliases.get(id), (res: Alias[]) => {
51+
const alias: Alias = res[0]
52+
for (let editAttrKey in editAttr) {
53+
assert((alias as any)[editAttrKey] == (editAttr as any)[editAttrKey])
54+
}
55+
})
56+
});
57+
it('should delete the previously created alias', async () => {
58+
await thenTestOrFail(mcc.aliases.delete({ items: [id] }), (res: MailcowResponse) => {
59+
expect(res[0].type).to.be.equal("success")
60+
})
61+
});
62+
})
1863
})
19-

0 commit comments

Comments
 (0)