зеркало из
1
0
Форкнуть 0

add server test; bug fix; date-time check (#235)

This commit is contained in:
YingXue 2020-03-09 17:07:16 -07:00 коммит произвёл GitHub
Родитель 7020135347
Коммит f78675ca03
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 168 добавлений и 21 удалений

2
package-lock.json сгенерированный
Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "azure-iot-explorer",
"version": "0.10.15",
"version": "0.10.16",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "azure-iot-explorer",
"version": "0.10.15",
"version": "0.10.16",
"description": "This project welcomes contributions and suggestions. Most contributions require you to agree to a\r Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us\r the rights to use your contribution. For details, visit https://cla.microsoft.com.",
"main": "public/electron.js",
"build": {

Просмотреть файл

@ -12,6 +12,7 @@ export interface ParsedJsonSchema {
enumNames?: string[];
format?: string;
items?: any; // tslint:disable-line: no-any
pattern?: string;
properties?: {};
required?: string[];
title?: string;

Просмотреть файл

@ -11,7 +11,7 @@ import {
} from './selectors';
import { getInitialState } from '../api/shared/testHelper';
describe('getDigitalTwinInterfacePropertiesSelector', () => {
describe('getAzureResourceSelector', () => {
const state = getInitialState();
const hostName = 'testhub.azure-devices.net';
state.azureResourceState = Record({

Просмотреть файл

@ -82,7 +82,7 @@ describe('parse interface model definition to Json schema', () => {
interfacePropertyDefinition.schema = 'datetime';
expect(parseInterfacePropertyToJsonSchema(interfacePropertyDefinition).type).toEqual('string');
expect(parseInterfacePropertyToJsonSchema(interfacePropertyDefinition).format).toEqual('date-time');
expect(parseInterfacePropertyToJsonSchema(interfacePropertyDefinition).pattern).toEqual('^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$');
interfacePropertyDefinition.schema = 'integer';
expect(parseInterfacePropertyToJsonSchema(interfacePropertyDefinition).type).toEqual('integer');

Просмотреть файл

@ -59,7 +59,7 @@ const parseInterfacePropertyHelper = (property: PropertyContent): ParsedJsonSch
case 'datetime':
return {
description: getDescription(property),
format: 'date-time',
pattern: '^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$', // regex for ISO 8601
title: property.name,
type: 'string',
};

Просмотреть файл

@ -0,0 +1,147 @@
/***********************************************************
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License
**********************************************************/
import 'jest';
import * as ServerBase from './serverBase';
describe('serverBase', () => {
const mockRequest = (bodyData?: any) => { // tslint:disable-line:no-any
return { body: bodyData } as any; // tslint:disable-line:no-any
};
const mockResponse = () => {
const res = {status: undefined, json: undefined, send: undefined};
res.status = jest.fn().mockReturnValue(res);
res.send = jest.fn().mockReturnValue(res);
res.json = jest.fn().mockReturnValue(res);
return res as any; // tslint:disable-line:no-any
};
context('handleDataPlanePostRequest', () => {
it('returns 400 if body is not provided', async () => {
const req = mockRequest();
const res = mockResponse();
await ServerBase.handleDataPlanePostRequest(req, res);
expect(res.status).toHaveBeenCalledWith(400); // tslint:disable-line:no-magic-numbers
});
});
context('handlhandleCloudToDevicePostRequesteDataPlanePostRequest', () => {
it('returns 400 if body is not provided', async () => {
const req = mockRequest();
const res = mockResponse();
await ServerBase.handleCloudToDevicePostRequest(req, res);
expect(res.status).toHaveBeenCalledWith(400); // tslint:disable-line:no-magic-numbers
});
});
context('handleEventHubMonitorPostRequest', () => {
it('returns 400 if body is not provided', async () => {
const req = mockRequest();
const res = mockResponse();
await ServerBase.handleEventHubMonitorPostRequest(req, res);
expect(res.status).toHaveBeenCalledWith(400); // tslint:disable-line:no-magic-numbers
});
it('calls eventHubProvider when body is provided', async () => {
const req = mockRequest('testBody');
const res = mockResponse();
const promise = {then: jest.fn()} as any; // tslint:disable-line:no-any
jest.spyOn(ServerBase, 'eventHubProvider').mockReturnValue(promise);
await ServerBase.handleEventHubMonitorPostRequest(req, res);
expect(ServerBase.eventHubProvider).toBeCalled();
});
});
context('handleEventHubStopPostRequest ', () => {
it('returns 400 if body is not provided', async () => {
const req = mockRequest();
const res = mockResponse();
await ServerBase.handleEventHubStopPostRequest (req, res);
expect(res.status).toHaveBeenCalledWith(400); // tslint:disable-line:no-magic-numbers
});
it('calls stopClient when body is provided', async () => {
const req = mockRequest('testBody');
const res = mockResponse();
const promise = {then: jest.fn()} as any; // tslint:disable-line:no-any
jest.spyOn(ServerBase, 'stopClient').mockReturnValue(promise);
await ServerBase.handleEventHubStopPostRequest(req, res);
expect(ServerBase.stopClient).toBeCalled();
});
});
context('handleModelRepoPostRequest', () => {
it('returns 400 if body is not provided', async () => {
const req = mockRequest();
const res = mockResponse();
await ServerBase.handleModelRepoPostRequest(req, res);
expect(res.status).toHaveBeenCalledWith(400); // tslint:disable-line:no-magic-numbers
});
it('returns 500 if response is error', async () => {
const req = mockRequest('test');
const res = mockResponse();
await ServerBase.handleModelRepoPostRequest(req, res);
expect(res.status).toHaveBeenCalledWith(500); // tslint:disable-line:no-magic-numbers
});
});
context('addPropertiesToCloudToDeviceMessage', () => {
it('add system properties to message', async () => {
const message: any = {properties: new Map()}; // tslint:disable-line:no-any
const properties = [
{
isSystemProperty: true,
key: 'ack',
value: '1',
},
{
isSystemProperty: true,
key: 'contentType',
value: 'json',
},
{
isSystemProperty: true,
key: 'correlationId',
value: '2',
},
{
isSystemProperty: true,
key: 'contentEncoding',
value: '3',
},
{
isSystemProperty: true,
key: 'expiryTimeUtc',
value: '4',
},
{
isSystemProperty: true,
key: 'messageId',
value: '5',
},
{
isSystemProperty: true,
key: 'lockToken',
value: '6',
}
];
ServerBase.addPropertiesToCloudToDeviceMessage(message, properties);
expect(message.ack).toEqual('1');
expect(message.contentType).toEqual('json');
expect(message.correlationId).toEqual('2');
expect(message.contentEncoding).toEqual('3');
expect(message.expiryTimeUtc).toEqual(4); // tslint:disable-line:no-magic-numbers
expect(message.messageId).toEqual('5');
expect(message.lockToken).toEqual('6');
});
});
});

Просмотреть файл

@ -14,7 +14,8 @@ import { generateDataPlaneRequestBody, generateDataPlaneResponse } from './dataP
const SERVER_ERROR = 500;
const BAD_REQUEST = 400;
const SUCCESS = 200;
const NOT_FOUND = 400;
const NOT_FOUND = 404;
const CONFLICT = 409;
const SERVER_WAIT = 3000; // how long we'll let the call for eventHub messages run in non-socket
const receivers: ReceiveHandler[] = [];
const IOTHUB_CONNECTION_DEVICE_ID = 'iothub-connection-device-id';
@ -55,7 +56,7 @@ export default class ServerBase {
}
const dataPlaneUri = '/api/DataPlane';
const handleDataPlanePostRequest = (req: express.Request, res: express.Response) => {
export const handleDataPlanePostRequest = (req: express.Request, res: express.Response) => {
try {
if (!req.body) {
res.status(BAD_REQUEST).send();
@ -75,7 +76,7 @@ const handleDataPlanePostRequest = (req: express.Request, res: express.Response)
};
const cloudToDeviceUri = '/api/CloudToDevice';
const handleCloudToDevicePostRequest = (req: express.Request, res: express.Response) => {
export const handleCloudToDevicePostRequest = (req: express.Request, res: express.Response) => {
try {
if (!req.body) {
res.status(BAD_REQUEST).send();
@ -102,7 +103,7 @@ const handleCloudToDevicePostRequest = (req: express.Request, res: express.Respo
};
const eventHubMonitorUri = '/api/EventHub/monitor';
const handleEventHubMonitorPostRequest = (req: express.Request, res: express.Response) => {
export const handleEventHubMonitorPostRequest = (req: express.Request, res: express.Response) => {
try {
if (!req.body) {
res.status(BAD_REQUEST).send();
@ -113,7 +114,7 @@ const handleEventHubMonitorPostRequest = (req: express.Request, res: express.Res
res.status(SUCCESS).send(result);
});
} else {
res.status(NOT_FOUND).send('Client currently stopping');
res.status(CONFLICT).send('Client currently stopping');
}
} catch (error) {
res.status(SERVER_ERROR).send(error);
@ -121,7 +122,7 @@ const handleEventHubMonitorPostRequest = (req: express.Request, res: express.Res
};
const eventHubStopUri = '/api/EventHub/stop';
const handleEventHubStopPostRequest = (req: express.Request, res: express.Response) => {
export const handleEventHubStopPostRequest = (req: express.Request, res: express.Response) => {
try {
if (!req.body) {
res.status(BAD_REQUEST).send();
@ -139,7 +140,7 @@ const handleEventHubStopPostRequest = (req: express.Request, res: express.Respon
};
const modelRepoUri = '/api/ModelRepo';
const handleModelRepoPostRequest = (req: express.Request, res: express.Response) => {
export const handleModelRepoPostRequest = (req: express.Request, res: express.Response) => {
try {
if (!req.body) {
res.status(BAD_REQUEST).send();
@ -165,7 +166,7 @@ const handleModelRepoPostRequest = (req: express.Request, res: express.Response)
};
// tslint:disable-next-line:cyclomatic-complexity
const addPropertiesToCloudToDeviceMessage = (message: CloudToDeviceMessage, properties: Array<{key: string, value: string, isSystemProperty: boolean}>) => {
export const addPropertiesToCloudToDeviceMessage = (message: CloudToDeviceMessage, properties: Array<{key: string, value: string, isSystemProperty: boolean}>) => {
if (!properties || properties.length === 0) {
return;
}
@ -176,18 +177,16 @@ const addPropertiesToCloudToDeviceMessage = (message: CloudToDeviceMessage, prop
message.ack = property.value;
break;
case 'contentType':
// tslint:disable-next-line:no-any
message.contentType = property.value as any;
message.contentType = property.value as any; // tslint:disable-line:no-any
break;
case 'correlationId':
message.correlationId = property.value;
break;
case 'contentEncoding':
message.correlationId = property.value;
message.contentEncoding = property.value as any; // tslint:disable-line:no-any
break;
case 'expiryTimeUtc':
// tslint:disable-next-line:radix
message.expiryTimeUtc = parseInt(property.value);
message.expiryTimeUtc = parseInt(property.value); // tslint:disable-line:radix
break;
case 'messageId':
message.messageId = property.value;
@ -207,7 +206,7 @@ const addPropertiesToCloudToDeviceMessage = (message: CloudToDeviceMessage, prop
};
// tslint:disable-next-line:cyclomatic-complexity
const eventHubProvider = async (res: any, body: any) => { // tslint:disable-line: no-any
export const eventHubProvider = async (res: any, body: any) => { // tslint:disable-line: no-any
try {
if (!eventHubClientStopping) {
if (!client || connectionString !== body.connectionString) {
@ -228,7 +227,7 @@ const eventHubProvider = async (res: any, body: any) => { // tslint:disable-lin
return handleMessages(body.deviceId, client, hubInfo, partitionIds, startTime, !!body.fetchSystemProperties, body.consumerGroup);
} else {
res.status(NOT_FOUND).send('Client currently stopping');
res.status(CONFLICT).send('Client currently stopping');
}
} catch (error) {
res.status(SERVER_ERROR).send(error);
@ -249,7 +248,7 @@ const stopReceivers = async () => {
);
};
const stopClient = async () => {
export const stopClient = async () => {
return stopReceivers().then(() => {
return client && client.close().then(() => {
client = null;