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

add api tests; small fixes and cleanup (#104)

This commit is contained in:
YingXue 2019-09-09 13:33:09 -07:00 коммит произвёл GitHub
Родитель b7da8abad8
Коммит b83eeff57f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 1187 добавлений и 89 удалений

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

@ -6,6 +6,9 @@ import { setIconOptions } from "office-ui-fabric-react/lib/Styling";
import * as Enzyme from "enzyme";
import * as Adapter from "enzyme-adapter-react-16";
global['Headers'] = () => {};
window.parent.fetch = jest.fn();
// suppress icon warnings.
setIconOptions({
disableWarnings: true,

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

@ -5579,7 +5579,6 @@
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -5598,7 +5597,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -24,10 +24,10 @@ import { Twin, Device, DataPlaneResponse } from '../models/device';
import { DeviceIdentity } from '../models/deviceIdentity';
import { DigitalTwinInterfaces } from '../models/digitalTwinModels';
const DATAPLANE_CONTROLLER_ENDPOINT = `${CONTROLLER_API_ENDPOINT}${DATAPLANE}`;
export const DATAPLANE_CONTROLLER_ENDPOINT = `${CONTROLLER_API_ENDPOINT}${DATAPLANE}`;
const EVENTHUB_CONTROLLER_ENDPOINT = `${CONTROLLER_API_ENDPOINT}${EVENTHUB}`;
const EVENTHUB_MONITOR_ENDPOINT = `${EVENTHUB_CONTROLLER_ENDPOINT}${MONITOR}`;
const EVENTHUB_STOP_ENDPOINT = `${EVENTHUB_CONTROLLER_ENDPOINT}${STOP}`;
export const EVENTHUB_MONITOR_ENDPOINT = `${EVENTHUB_CONTROLLER_ENDPOINT}${MONITOR}`;
export const EVENTHUB_STOP_ENDPOINT = `${EVENTHUB_CONTROLLER_ENDPOINT}${STOP}`;
const PAGE_SIZE = 20;
export interface DataPlaneRequest {
@ -54,7 +54,7 @@ export interface CloudToDeviceMethodResult {
}
// We can do something more sophisticated with agents and a factory
const request = async (endpoint: string, parameters: any) => { // tslint:disable-line
export const request = async (endpoint: string, parameters: any) => { // tslint:disable-line
return fetch(
endpoint,
{
@ -71,7 +71,7 @@ const request = async (endpoint: string, parameters: any) => { // tslint:disable
);
};
const dataPlaneConnectionHelper = (parameters: DataPlaneParameters) => {
export const dataPlaneConnectionHelper = (parameters: DataPlaneParameters) => {
if (!parameters || !parameters.connectionString) {
return;
}
@ -101,17 +101,13 @@ const dataPlaneResponseHelper = async (response: Response) => {
}
// error case
if (!result) {
throw new Error();
}
if (result.ExceptionMessage && result.Message) {
throw new Error(`${result.Message}: ${result.ExceptionMessage}`);
}
else if (!!result.ExceptionMessage || result.Message) {
throw new Error(!!result.ExceptionMessage ? result.ExceptionMessage : result.Message);
if (result && result.body) {
if (result.body.Message || result.body.ExceptionMessage) {
throw new Error(result.body.Message || result.body.ExceptionMessage);
}
}
throw new Error(result);
throw new Error();
};
export const fetchDeviceTwin = async (parameters: FetchDeviceTwinParameters): Promise<Twin> => {
@ -383,7 +379,7 @@ export const deleteDevices = async (parameters: DeleteDevicesParameters) => {
const dataPlaneRequest: DataPlaneRequest = {
body: JSON.stringify(deviceDeletionInstructions),
hostName: connectionInfo.connectionInfo.hostName,
httpMethod: 'post',
httpMethod: HTTP_OPERATION_TYPES.Post,
path: `devices`,
sharedAccessSignature: connectionInfo.sasToken,
};
@ -419,7 +415,7 @@ export const monitorEvents = async (parameters: MonitorEventsParameters): Promis
export const stopMonitoringEvents = async (): Promise<void> => {
try {
const response = await request(EVENTHUB_STOP_ENDPOINT, {});
await request(EVENTHUB_STOP_ENDPOINT, {});
} catch (error) {
throw error;
}

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

@ -0,0 +1,117 @@
/***********************************************************
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License
**********************************************************/
import * as DigitalTwinsModelService from './digitalTwinsModelService';
import { API_VERSION, DIGITAL_TWIN_API_VERSION } from '../../constants/apiConstants';
import { HTTP_OPERATION_TYPES } from '../constants';
describe('digitalTwinsModelService', () => {
context('fetchModel', () => {
const parameters = {
expand: undefined,
id: 'urn:azureiot:ModelDiscovery:ModelInformation:1',
repoServiceHostName: 'canary-repo.azureiotrepository.com',
repositoryId: 'repositoryId',
token: 'SharedAccessSignature sr=canary-repo.azureiotrepository.com&sig=123&rid=repositoryId'
};
it('calls fetch with specified parameters', () => {
DigitalTwinsModelService.fetchModel(parameters);
const expandQueryString = parameters.expand ? `&expand=true` : ``;
const repositoryQueryString = parameters.repositoryId ? `&repositoryId=${parameters.repositoryId}` : '';
const apiVersionQuerySTring = `?${API_VERSION}${DIGITAL_TWIN_API_VERSION}`;
const queryString = `${apiVersionQuerySTring}${expandQueryString}${repositoryQueryString}`;
const modelIdentifier = encodeURIComponent(parameters.id);
const resourceUrl = `https://${parameters.repoServiceHostName}/models/${modelIdentifier}${queryString}`;
const controllerRequest = {
headers: {
'Accept': 'application/json',
'Authorization': parameters.token || '',
'Content-Type': 'application/json'
},
method: HTTP_OPERATION_TYPES.Get,
uri: resourceUrl
};
const fetchModelParameters = {
body: JSON.stringify(controllerRequest),
cache: 'no-cache',
credentials: 'include',
headers: new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
}),
method: HTTP_OPERATION_TYPES.Post
};
expect(fetch).toBeCalledWith(DigitalTwinsModelService.CONTROLLER_ENDPOINT, fetchModelParameters);
});
it('returns model when response is 200', async () => {
// tslint:disable
const model = {
'@id': 'urn:azureiot:Client:SDKInformation:1',
'@type': 'Interface',
'displayName': 'Digital Twin Client SDK Information',
'contents': [
{
'@type': 'Property',
'name': 'language',
'displayName': 'SDK Language',
'schema': 'string',
'description': 'The language for the Digital Twin client SDK. For example, Java.'
},
{
'@type': 'Property',
'name': 'version',
'displayName': 'SDK Version',
'schema': 'string',
'description': 'Version of the Digital Twin client SDK. For example, 1.3.45.'
},
{
'@type': 'Property',
'name': 'vendor',
'displayName': 'SDK Vendor',
'schema': 'string',
'description': 'Name of the vendor who authored the SDK. For example, Microsoft.'
}
],
'@context': 'http://azureiot.com/v1/contexts/IoTModel.json'
};
const response = {
json: () => model,
headers: {has: () => {}},
ok: true
} as any;
// tslint:enable
jest.spyOn(window, 'fetch').mockResolvedValue(response);
const result = await DigitalTwinsModelService.fetchModel(parameters);
expect(result).toEqual({
createdOn: '',
etag: '',
lastUpdated: '',
model,
modelId: '',
publisherId: '',
publisherName: ''
});
});
it('throws Error when response is not OK', async () => {
// tslint:disable
const response = {
ok: false,
statusText: 'Not found'
} as any;
// tslint:enable
jest.spyOn(window, 'fetch').mockResolvedValue(response);
await expect(DigitalTwinsModelService.fetchModel(parameters)).rejects.toThrow(new Error('Not found'));
});
});
});

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

@ -81,27 +81,19 @@ export interface RepoConnectionSettings {
repositoryId?: string;
}
const CONTROLLER_ENDPOINT = `${CONTROLLER_API_ENDPOINT}${MODELREPO}`;
const CONTROLLER_PASSTHROUGH = true;
export const CONTROLLER_ENDPOINT = `${CONTROLLER_API_ENDPOINT}${MODELREPO}`;
const request = async (requestInit: RequestInitWithUri) => {
if (CONTROLLER_PASSTHROUGH) {
return fetch(
CONTROLLER_ENDPOINT,
{
body: JSON.stringify(requestInit),
cache: 'no-cache',
credentials: 'include',
headers: new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
}),
method: HTTP_OPERATION_TYPES.Post
}
);
} else {
return fetch(
requestInit.uri,
requestInit
);
}
return fetch(
CONTROLLER_ENDPOINT,
{
body: JSON.stringify(requestInit),
cache: 'no-cache',
credentials: 'include',
headers: new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
}),
method: HTTP_OPERATION_TYPES.Post
}
);
};

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

@ -21,7 +21,6 @@ $nav-width: 20%;
}
.device-content-nav-bar {
overflow-y: auto;
@include nav-bar;
display: flex;
flex-Direction: column;
width: $nav-width;

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

@ -3,8 +3,8 @@
* Licensed under the MIT License
**********************************************************/
.nav-label{
font-weight: bold;
padding-left: 10px;
font-weight: bold !important;
padding-left: 32px !important;
}
.navToggle {
margin-left:5px;

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

@ -1,32 +0,0 @@
/***********************************************************
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License
**********************************************************/
@import 'variables';
@import 'mixins';
.top-nav-bar {
position: relative;
left: 0px;
right: 0px;
top: 0px;
background-color: white;
z-index: 10;
@include nav-bar;
.ms-Dropdown-container {
@media screen and (min-width: $screenSize) {
width: 200px;
float: right;
height: 50px;
.nav-bar-language-dropdown {
margin: 8px 8px;
}
.ms-Dropdown-items {
width: 200px;
}
}
@media screen and (max-width: $screenSize) {
display: none;
}
}
}

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

@ -4,19 +4,6 @@
**********************************************************/
@import 'variables';
@mixin nav-bar {
min-height: 50px;
@media screen and (min-width: $screenSize) {
border: {
bottom: {
width: 1px;
style: solid;
color: $navBarBorderColor;
}
}
}
}
@mixin form-control-readonly {
border-width: 0px;
color: $textfield-disabled-font;

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

@ -37,7 +37,7 @@ export const generateDataPlaneResponse = (httpRes: request.Response, body: any,
};
// tslint:disable-next-line:cyclomatic-complexity
export const processDataPlaneResponse = (httpRes: request.Response, body: any): {body: any, statusCode?: number} => { // tslint:disable-line:no-any
export const processDataPlaneResponse = (httpRes: request.Response, body: any): {body: {body: any, headers?: any}, statusCode?: number} => { // tslint:disable-line:no-any
if (httpRes) {
if (httpRes.headers && httpRes.headers[DEVICE_STATUS_HEADER]) { // handles happy failure cases when error code is returned as a header
return {