Skip to content

Commit

Permalink
DEVEXP-337: e2e tests proto
Browse files Browse the repository at this point in the history
  • Loading branch information
asein-sinch committed Mar 27, 2024
1 parent 49f821e commit e50d061
Show file tree
Hide file tree
Showing 15 changed files with 665 additions and 52 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"ignoreRegExpLiterals": true,
"ignorePattern": "^import.+|test"
}
]
],
"new-cap": "off"
}
}
49 changes: 49 additions & 0 deletions .github/workflows/run_ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Build and test Sinch Node.js SDK

on:
push:
branches:
- 'main'
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: yarn install
- run: npx eslint "packages/**/src/**/*.ts"
- run: npx eslint "packages/**/tests/**/*.ts"
- run: yarn run build
- run: yarn run test

# Start the mock server
- name: Start the mock server
run: |
git clone https://github.com/sinch/doppelganger.git sinch-sdk-mockserver
cd sinch-sdk-mockserver
git checkout upgrade-to-typescript
yarn install
yarn compile
AUTH_PORT=8020 NUMBERS_PORT=8021 SMS_PORT=8022 CONVERSATION_PORT=8023 VERIFICATION_PORT=8024 VOICE_PORT=8025 FAX_PORT=8026 node --experimental-specifier-resolution=node dist/index.js
# Wait for mock server to start
- name: Wait for Mock Server
run: sleep 15

# Run tests
- run: yarn run e2e

# Stop mock server after tests
- name: Stop Mock Server
run: |
cd mockserver
pkill -f "node --experimental-specifier-resolution=node dist/index.js"
26 changes: 0 additions & 26 deletions .github/workflows/run_tests.yaml

This file was deleted.

4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@
"examples/*"
],
"scripts": {
"lerna": "lerna",
"bootstrap": "npx lerna bootstrap",
"build": "lerna run build",
"test": "jest",
"e2e": "cd e2e && yarn && yarn run test:cucumber"
"e2e": "lerna run test:cucumber"
},
"keywords": [],
"devDependencies": {
Expand Down
8 changes: 8 additions & 0 deletions packages/fax/cucumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
default: [
'tests-e2e/features/**/*.feature',
'--require-module ts-node/register',
'--require tests-e2e/features/step-definitions/**/*.ts',
`--format-options '{"snippetInterface": "synchronous"}'`,
].join(' '),
};
7 changes: 5 additions & 2 deletions packages/fax/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
"scripts": {
"build": "yarn run clean && yarn run compile",
"clean": "rimraf dist tsconfig.tsbuildinfo",
"compile": "tsc -p tsconfig.build.json && tsc -p tsconfig.tests.json && rimraf dist/tests && rimraf tsconfig.build.tsbuildinfo"
"compile": "tsc -p tsconfig.build.json && tsc -p tsconfig.tests.json && rimraf dist/tests && rimraf tsconfig.build.tsbuildinfo",
"test:e2e": "cucumber-js"
},
"dependencies": {
"@sinch/sdk-client": "^0.0.4"
},
"devDependencies": {},
"devDependencies": {
"@cucumber/cucumber": "^10.3.1"
},
"publishConfig": {
"directory": "dist"
}
Expand Down
8 changes: 6 additions & 2 deletions packages/fax/src/rest/v3/fax-domain-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,15 @@ export class FaxDomainApi implements Api {
throw new Error('Invalid configuration for the Fax API: '
+ '"projectId", "keyId" and "keySecret" values must be provided');
}
return {
const apiClientOptions: ApiClientOptions = {
projectId: params.projectId,
requestPlugins: [new Oauth2TokenRequest( params.keyId, params.keySecret)],
requestPlugins: [new Oauth2TokenRequest( params.keyId, params.keySecret, params.authBaseUrl)],
useServicePlanId: false,
};
if (params.requestPlugins && params.requestPlugins.length > 0) {
apiClientOptions.requestPlugins?.push(...params.requestPlugins);
}
return apiClientOptions;
}

}
4 changes: 2 additions & 2 deletions packages/fax/src/rest/v3/faxes/faxes-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,14 +238,14 @@ export class FaxesApi extends FaxDomainApi {
headers['Content-Type'] = 'application/json';
body = JSON.stringify(data['sendFaxRequestBody']);
} else {
const formParams:any = {};
const formParams: any = {};
const requestData = data.sendFaxRequestBody as FaxRequestFormData;
if( requestData.to ) { formParams['to'] = requestData.to; }
if( requestData.file ) { formParams['file'] = requestData.file; }
if( requestData.from ) { formParams['from'] = requestData.from; }
if( requestData.contentUrl ) { formParams['contentUrl'] = requestData.contentUrl; }
if( requestData.headerText ) { formParams['headerText'] = requestData.headerText; }
if( requestData.headerPageNumbers ) { formParams['headerPageNumbers'] = requestData.headerPageNumbers; }
if( requestData.headerPageNumbers ) { formParams.headerPageNumbers = requestData.headerPageNumbers.toString(); }
if( requestData.headerTimeZone ) { formParams['headerTimeZone'] = requestData.headerTimeZone; }
if( requestData.retryDelaySeconds ) { formParams['retryDelaySeconds'] = requestData.retryDelaySeconds; }
if( requestData.labels ) { formParams['labels'] = requestData.labels; }
Expand Down
32 changes: 32 additions & 0 deletions packages/fax/tests-e2e/features/faxes.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Feature: [Fax][Faxes]
E2E test for Fax/Faxes API

Scenario: [Send] send a fax
Given the Fax service is available
When I send a request to send a fax
Then the response contains a fax object

Scenario: [Get] retrieve a fax
Given the Fax service is available
When I send a request to retrieve a fax
Then the response contains a fax object

Scenario: [List] lists faxes
Given the Fax service is available
When I send a request to list faxes
Then the response contains "2" faxes

Scenario: [List] lists all faxes
Given the Fax service is available
When I send a request to list all the faxes
Then the faxes list contains "3" faxes

Scenario: [DownloadContent] download a fax content
Given the Fax service is available
When I send a request to download a fax content as PDF
Then the response contains a PDF document

Scenario: [DeleteContent] delete a fax content
Given the Fax service is available
When I send a request to delete a fax content on the server
Then the response contains no data
80 changes: 80 additions & 0 deletions packages/fax/tests-e2e/features/step-definitions/faxes.steps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Given, When, Then } from '@cucumber/cucumber';
import { Fax, FaxService } from '../../../src';
import { FileBuffer, PageResult } from '@sinch/sdk-client';
import * as assert from 'assert';

let faxService: FaxService;
let listResponse: PageResult<Fax>;
const faxList: Fax[] = [];
let fax: Fax;
let fileBuffer: FileBuffer;
let deleteContentResponse: void;

Given('the Fax service is available', function () {
faxService = new FaxService({
projectId: 'projectId',
keyId: 'keyId',
keySecret: 'keySecret',
authBaseUrl: 'http://localhost:5039',
});
faxService.setBasePath('http://localhost:5045');
});

When('I send a request to list faxes', async function () {
listResponse = await faxService.faxes.list({});
});

When('I send a request to list all the faxes', async function () {
for await (const fax of faxService.faxes.list({})) {
faxList.push(fax);
}
});

When('I send a request to send a fax', async function () {
fax = await faxService.faxes.send({
sendFaxRequestBody: {
to: '+1234567890',
contentUrl: 'https://developers.sinch.com/fax/fax.pdf',
},
});
});

When('I send a request to retrieve a fax', async function () {
fax = await faxService.faxes.get({
id: 'FAXID',
});
});

When('I send a request to download a fax content as PDF', async function () {
fileBuffer = await faxService.faxes.downloadContent({
id: 'FAXID',
});
});

When('I send a request to delete a fax content on the server', async function () {
deleteContentResponse = await faxService.faxes.deleteContent({
id: 'FAXID',
});
});

Then('the response contains {string} faxes', function (expectedAnswer: string) {
const expectedFaxes = parseInt(expectedAnswer, 10);
assert.strictEqual(listResponse.data.length, expectedFaxes);
});

Then('the faxes list contains {string} faxes', function (expectedAnswer: string) {
const expectedFaxes = parseInt(expectedAnswer, 10);
assert.strictEqual(faxList.length, expectedFaxes);
});

Then('the response contains a fax object', function () {
assert.ok(fax.id);
});

Then('the response contains a PDF document', function () {
assert.ok(fileBuffer.fileName);
});

Then('the response contains no data', function () {
assert.deepEqual(deleteContentResponse, {});
});
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ class SinchIterator<T> implements AsyncIterator<T> {
return updateQueryParamsAndSendRequest(
this.apiClient, newParams, requestOptions, this.paginatedOperationProperties);
}
if (this.paginatedOperationProperties.pagination === PaginationEnum.PAGE) {
if (this.paginatedOperationProperties.pagination === PaginationEnum.PAGE
|| this.paginatedOperationProperties.pagination === PaginationEnum.PAGE3) {
const newParams = {
page: pageResult.nextPageValue,
};
Expand Down Expand Up @@ -133,7 +134,7 @@ export const createNextPageMethod = <T>(
newParams = {
pageToken: nextPageValue,
};
} else if (context.pagination === PaginationEnum.PAGE) {
} else if (context.pagination === PaginationEnum.PAGE || context.pagination === PaginationEnum.PAGE3) {
newParams = {
page: nextPageValue,
};
Expand Down
6 changes: 3 additions & 3 deletions packages/sdk-client/src/client/api-fetch-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,9 @@ export class ApiFetchClient extends ApiClient {

if (type === 'multipart/form-data') {
const formData: FormData = new FormData();
for (const i in data) {
if (Object.prototype.hasOwnProperty.call(data, i)) {
formData.append(i, data[i]);
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
formData.append(key, data[key]);
}
}
encodedData = formData;
Expand Down
18 changes: 17 additions & 1 deletion packages/sdk-client/src/domain/domain-interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { RequestPlugin } from '../plugins/core/request-plugin';
import { ResponsePlugin } from '../plugins/core/response-plugin';

export interface SinchClientParameters extends
Partial<UnifiedCredentials>,
Partial<ServicePlanIdCredentials>,
Partial<ApplicationCredentials> {}
Partial<ApplicationCredentials>,
Partial<ApiBaseUrl>,
Partial<Plugins> {}

export interface UnifiedCredentials {
/** The project ID associated with the API Client. You can find this on your [Dashboard](https://dashboard.sinch.com/account/access-keys). */
Expand Down Expand Up @@ -34,6 +39,17 @@ export interface ApplicationCredentials {
voiceRegion?: VoiceRegion;
}

export interface ApiBaseUrl {
authBaseUrl?: string;
numbersBaseUrl?: string;
smsBaseUrl?: string;
}

export interface Plugins {
requestPlugins?: RequestPlugin[];
responsePlugins?: ResponsePlugin<any>[];
}

export const isUnifiedCredentials = (credentials: any): credentials is UnifiedCredentials => {
const candidate = (credentials) as UnifiedCredentials;
return candidate.projectId !== undefined
Expand Down
1 change: 1 addition & 0 deletions packages/sdk-client/src/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './core';
export * from './additional-headers';
export * from './api-token';
export * from './basicAuthentication';
export * from './exception';
Expand Down
Loading

0 comments on commit e50d061

Please sign in to comment.